OpenAPITools/openapi-generator · error · RuntimeException
Component %s name conflict during spec merge: '%s' is define
Error message
Component %s name conflict during spec merge: '%s' is defined in multiple specs with different definitions. Keeping the first definition.
What it means
MergedSpecBuilder.mergeComponentMap throws this when two merged specs declare the same component name (schema, parameter, response, securityScheme, ...) with DIFFERENT definitions and mergeConflictStrategy is FAIL. Identical duplicates are silently accepted; only differing definitions count as a conflict, where the first definition wins.
Source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java:809
mergeComponentMap(target.getSecuritySchemes(), source.getSecuritySchemes(), "securityScheme", target::addSecuritySchemes);
// OpenAPI 3.1 reusable path items — without this, operations referencing
// '#/components/pathItems/...' would dangle in the merged output.
mergeComponentMap(target.getPathItems(), source.getPathItems(), "pathItem", target::addPathItem);
}
private <T> void mergeComponentMap(Map<String, T> existing, Map<String, T> incoming,
String typeName, java.util.function.BiConsumer<String, T> adder) {
if (incoming == null) {
return;
}
incoming.forEach((name, value) -> {
if (existing != null && existing.containsKey(name)) {
if (!Objects.equals(existing.get(name), value)) {
String message = String.format(Locale.ROOT,
"Component %s name conflict during spec merge: '%s' is defined in multiple specs with different definitions. Keeping the first definition.",
typeName, name);
if (conflictStrategy == MergeConflictStrategy.FAIL) {
throw new RuntimeException(message);
}
LOGGER.warn(message);
}
// identical or keeping first — either way, skip
} else {
adder.accept(name, value);
}
});
}
private List<String> getAllSpecFilesInDirectory() {
Path rootDirectory = new File(inputSpecRootDirectory).toPath();
try (Stream<Path> pathStream = Files.walk(rootDirectory)) {
return pathStream
.filter(path -> !Files.isDirectory(path))
.filter(path -> {
String name = path.getFileName().toString().toLowerCase(Locale.ROOT);
return SPEC_EXTENSIONS.stream().anyMatch(name::endsWith);View on GitHub (pinned to fcec517be3)
Solutions
- Align the component definitions so they are identical (Objects.equals) across every spec file.
- Move the shared component into one canonical file and reference it via $ref from the other specs, removing the duplicates.
- Rename one of the conflicting components (e.g. StorePet vs Pet) and update its $refs.
- Drop the strict FAIL strategy if first-wins behavior is acceptable for your pipeline.
Example fix
# specs/a.yaml (before):
components:
schemas:
Pet: { type: object, properties: { id: {type: integer}, name: {type: string} } }
# specs/b.yaml (before):
components:
schemas:
Pet: { type: object, properties: { id: {type: string}, name: {type: string}, tag: {type: string} } }
# after — both files carry the byte-identical Pet schema, or b.yaml renames:
StorePet: { type: object, properties: { id: {type: string}, name: {type: string}, tag: {type: string} } } Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: fail when the same component name has different definitions across specs
Map<String, Object> merged = new HashMap<>();
for (String file : specFiles) {
OpenAPI api = new OpenAPIV3Parser().read(file);
if (api.getComponents() == null || api.getComponents().getSchemas() == null) continue;
api.getComponents().getSchemas().forEach((name, schema) -> {
Object prev = merged.get(name);
if (prev != null && !Objects.equals(prev, schema))
throw new IllegalStateException("Component '" + name + "' differs between specs");
merged.put(name, schema);
});
} Try / catch
try {
mergedSpec = mergedSpecBuilder.build();
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Component ") && e.getMessage().contains("name conflict during spec merge")) {
// diff the two component definitions, then align or rename them at source
throw new BuildException("Spec merge conflict: " + e.getMessage(), e);
}
throw e;
} Prevention
- Define shared components (schemas, parameters) once in a canonical file and $ref them instead of duplicating.
- Treat a silently-differing duplicate component as data drift: even on WARN strategy the merge keeps only the first definition, which can change generated models.
- Run a schema-diff check in CI when multiple specs reuse the same component names.
When it happens
Trigger: Directory merge where petstore.yaml defines schema 'Pet' with 4 properties and store.yaml defines 'Pet' with 6. existing.containsKey(name) is true, Objects.equals(existing.get(name), value) is false, and FAIL aborts the merge with the component type and name in the message.
Common situations: Shared DTOs copy-pasted between team specs that later drift out of sync; common parameter components like 'limitParam' defined differently per file; a shared components file merged together with specs that inline-repeat those components.
Related errors
- operationId conflict during spec merge: '%s' (%s %s) is alre
- Path+method conflict during spec merge: %s %s is defined in
- schema cannot be null with ref {ref}
- inputSpecFiles list is empty — nothing to merge
- Spec directory doesn't contain any specification
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/e6918ce944392d56.
Report an issue: GitHub.