{"record":{"id":"bcec907519e4deda","repo":"OpenAPITools/openapi-generator","slug":"path-method-conflict-during-spec-merge-s-s-is-d","errorCode":null,"errorMessage":"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.","messagePattern":"Path\\+method conflict during spec merge: (.+?) (.+?) 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\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java","lineNumber":716,"sourceCode":"     *       otherwise name+in); first wins on conflict</li>\n     *   <li>Servers: added if not already present by URL</li>\n     *   <li>Extensions: added if not already present by key</li>\n     *   <li>Summary and description: always kept from the first ({@code existing}) PathItem</li>\n     * </ul>\n     */\n    private void mergePathItem(PathItem existing, PathItem incoming, String pathKey) {\n        if (incoming.readOperationsMap() == null) {\n            return;\n        }\n        incoming.readOperationsMap().forEach((method, operation) -> {\n            if (existing.readOperationsMap() != null && existing.readOperationsMap().containsKey(method)) {\n                String message = String.format(Locale.ROOT,\n                        \"Path+method conflict during spec merge: %s %s is defined in multiple specs. \" +\n                        \"Unlike schema reuse, duplicate HTTP methods on the same path are not valid — \" +\n                        \"check that your spec files do not overlap. Keeping the first definition.\",\n                        method, pathKey);\n                if (conflictStrategy == MergeConflictStrategy.FAIL) {\n                    throw new RuntimeException(message);\n                }\n                LOGGER.warn(message);\n                // WARN: keep the first (existing) operation, skip the incoming one.\n                return;\n            }\n            existing.operation(method, operation);\n        });\n\n        // Merge path-level parameters (first wins on conflict). Identity is the $ref value when the\n        // parameter is a reference; otherwise name+in. Without this, multiple distinct $ref\n        // parameters would all collapse to the key \"null:null\" and all but the first would be lost.\n        if (incoming.getParameters() != null) {\n            List<Parameter> merged = existing.getParameters() != null\n                    ? new ArrayList<>(existing.getParameters()) : new ArrayList<>();\n            Set<String> existingKeys = merged.stream()\n                    .map(MergedSpecBuilder::parameterIdentity)\n                    .collect(Collectors.toSet());\n            for (Parameter p : incoming.getParameters()) {","sourceCodeStart":698,"sourceCodeEnd":734,"githubUrl":"https://github.com/OpenAPITools/openapi-generator/blob/fcec517be3cf5b7964296bcba25fbc97541484e7/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java#L698-L734","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# specs/a.yaml and specs/b.yaml (before) — both define:\npaths:\n  /users:\n    get: ...\n# after — only specs/a.yaml defines /users; specs/b.yaml drops it\n# or rename in b.yaml:\npaths:\n  /store/users:\n    get: ...","handlingStrategy":"validation","validationCode":"// Pre-flight: fail on duplicate path+method across spec files before merging\nSet<String> seen = new HashSet<>();\nfor (String file : specFiles) {\n    OpenAPI api = new OpenAPIV3Parser().read(file);\n    api.getPaths().forEach((path, item) ->\n        item.readOperationsMap().forEach((method, op) -> {\n            if (!seen.add(method + \" \" + path))\n                throw new IllegalStateException(method + \" \" + path + \" defined again in \" + file);\n        }));\n}","typeGuard":null,"tryCatchPattern":"try {\n    mergedSpec = mergedSpecBuilder.build();\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Path+method conflict during spec merge\")) {\n        // message names the method and path; keep the intended definition and delete the other\n        throw new BuildException(\"Spec merge conflict: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["openapi","spec-merge","path-conflict","duplicate-endpoint","java"],"backgroundTag":"duplicate-path-method","analyzedSha":"fcec517be3cf5b7964296bcba25fbc97541484e7","analyzedAt":"2026-08-22T11:13:11.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}