OpenAPITools/openapi-generator · error · RuntimeException
Path+method conflict during spec merge: %s %s is defined in
Error message
Path+method conflict during spec merge: %s %s is defined in multiple specs. Unlike schema reuse, duplicate HTTP methods on the same path are not valid — check that your spec files do not overlap. Keeping the first definition.
What it means
MergedSpecBuilder.mergePathItem throws this when the same path + HTTP method is defined in more than one input spec and mergeConflictStrategy is FAIL. Unlike schemas, two operations on the same method+path cannot coexist in a valid OpenAPI document, so only one can survive — the merge keeps the first definition and aborts under FAIL.
Source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java:716
* otherwise name+in); first wins on conflict</li>
* <li>Servers: added if not already present by URL</li>
* <li>Extensions: added if not already present by key</li>
* <li>Summary and description: always kept from the first ({@code existing}) PathItem</li>
* </ul>
*/
private void mergePathItem(PathItem existing, PathItem incoming, String pathKey) {
if (incoming.readOperationsMap() == null) {
return;
}
incoming.readOperationsMap().forEach((method, operation) -> {
if (existing.readOperationsMap() != null && existing.readOperationsMap().containsKey(method)) {
String message = String.format(Locale.ROOT,
"Path+method conflict during spec merge: %s %s is defined in multiple specs. " +
"Unlike schema reuse, duplicate HTTP methods on the same path are not valid — " +
"check that your spec files do not overlap. Keeping the first definition.",
method, pathKey);
if (conflictStrategy == MergeConflictStrategy.FAIL) {
throw new RuntimeException(message);
}
LOGGER.warn(message);
// WARN: keep the first (existing) operation, skip the incoming one.
return;
}
existing.operation(method, operation);
});
// Merge path-level parameters (first wins on conflict). Identity is the $ref value when the
// parameter is a reference; otherwise name+in. Without this, multiple distinct $ref
// parameters would all collapse to the key "null:null" and all but the first would be lost.
if (incoming.getParameters() != null) {
List<Parameter> merged = existing.getParameters() != null
? new ArrayList<>(existing.getParameters()) : new ArrayList<>();
Set<String> existingKeys = merged.stream()
.map(MergedSpecBuilder::parameterIdentity)
.collect(Collectors.toSet());
for (Parameter p : incoming.getParameters()) {View on GitHub (pinned to fcec517be3)
Solutions
- De-duplicate: keep the path+method definition in exactly one spec file.
- If the endpoints are genuinely different, rename the path in one spec (e.g. /store/users vs /users).
- Remove the overlapping file from the merge input, or accept first-wins behavior by using the default WARN strategy instead of FAIL.
Example fix
# specs/a.yaml and specs/b.yaml (before) — both define:
paths:
/users:
get: ...
# after — only specs/a.yaml defines /users; specs/b.yaml drops it
# or rename in b.yaml:
paths:
/store/users:
get: ... Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: fail on duplicate path+method across spec files before merging
Set<String> seen = new HashSet<>();
for (String file : specFiles) {
OpenAPI api = new OpenAPIV3Parser().read(file);
api.getPaths().forEach((path, item) ->
item.readOperationsMap().forEach((method, op) -> {
if (!seen.add(method + " " + path))
throw new IllegalStateException(method + " " + path + " defined again in " + file);
}));
} Try / catch
try {
mergedSpec = mergedSpecBuilder.build();
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Path+method conflict during spec merge")) {
// message names the method and path; keep the intended definition and delete the other
throw new BuildException("Spec merge conflict: " + e.getMessage(), e);
}
throw e;
} Prevention
- Keep each path defined in exactly one spec file; put shared endpoints in a single owner file.
- Beware common utility paths like /health and /status sneaking into every team spec.
- Use the FAIL strategy in CI to detect accidental spec overlap instead of silently losing the second definition.
When it happens
Trigger: Directory merge where both spec files define 'get: /users'. When merging the second file, existing.readOperationsMap().containsKey(method) is true, and with FAIL the RuntimeException is thrown; with the default WARN the first definition is kept and the incoming one skipped.
Common situations: Two teams' specs that both expose /health or /status; a shared/common.yaml left in the merge directory alongside a spec that repeats the same endpoints; versioned specs (v1.yaml, v2.yaml) accidentally merged together.
Related errors
- operationId conflict during spec merge: '%s' (%s %s) is alre
- Component %s name conflict during spec merge: '%s' is define
- inputSpecFiles list is empty — nothing to merge
- Spec directory doesn't contain any specification
- No valid specifications found to merge
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/bcec907519e4deda.
Report an issue: GitHub.