{"record":{"id":"f6b9befb6b96594e","repo":"grpc-ecosystem/grpc-gateway","slug":"openapi-s-declares-q-but-s-declares-q","errorCode":null,"errorMessage":"openapi: %s declares %q but %s declares %q","messagePattern":"openapi: (.+?) declares %q but (.+?) declares %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openapiv3-merge/internal/merge/merge.go","lineNumber":275,"sourceCode":"// values that later inputs must not contradict.\nfunc mergeAll(docs []*document) (*document, error) {\n\tfirst := docs[0]\n\tout := &document{\n\t\tname:         \"merged\",\n\t\tOpenAPI:      first.OpenAPI,\n\t\tInfo:         first.Info,\n\t\tServers:      first.Servers,\n\t\tPaths:        newOrderedObject(),\n\t\tWebhooks:     newOrderedObject(),\n\t\tComponents:   &components{},\n\t\tExternalDocs: first.ExternalDocs,\n\t\textras:       newOrderedObject(),\n\t}\n\tseenTags := map[string]json.RawMessage{}\n\n\tfor _, d := range docs {\n\t\tif d.OpenAPI != out.OpenAPI {\n\t\t\treturn nil, fmt.Errorf(\"openapi: %s declares %q but %s declares %q\",\n\t\t\t\tfirst.name, out.OpenAPI, d.name, d.OpenAPI)\n\t\t}\n\t\t// info/servers/externalDocs and unknown top-level keys are first-wins,\n\t\t// silently. The first input's value is already in `out`; nothing to\n\t\t// do for later inputs.\n\t\tif err := mergeOrdered(\"paths\", out.Paths, d.Paths, d.name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := mergeOrdered(\"webhooks\", out.Webhooks, d.Webhooks, d.name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := mergeComponents(out.Components, d.Components, d.name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := mergeTags(out, seenTags, d); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := mergeSecurity(out, d); err != nil {","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/openapiv3-merge/internal/merge/merge.go#L257-L293","documentation":"Raised in mergeAll when two inputs declare different `openapi` version strings. The library's strict-merge policy requires all inputs to agree on the OpenAPI version; the first input's version establishes the expected value and any later contradicting input is rejected, naming both files and versions.","triggerScenarios":"Calling Merge with inputs where docs[0].OpenAPI != docs[i].OpenAPI — e.g. one file says \"3.1.0\" and another says \"3.0.3\" or \"3.1.1\".","commonSituations":"Mixing documents generated by different generator versions (one pinned to 3.0.x, another upgraded to 3.1), partially migrated specs, or vendored third-party specs pinned to a different version.","solutions":["Regenerate or update the mismatching document so its \"openapi\" version matches the first input","Pin all generator invocations to the same OpenAPI output version","If the older file is 3.0.x, migrate it to 3.1 first, then merge","Align dependency versions of the generator across packages"],"exampleFix":"// before (b.json)\n\"openapi\": \"3.0.3\"\n// after (b.json)\n\"openapi\": \"3.1.0\"","handlingStrategy":"validation","validationCode":"func versionsMatch(inputs []merge.Input) error {\n\tvar first string\n\tfor _, in := range inputs {\n\t\tvar doc struct { OpenAPI string `json:\"openapi\"` }\n\t\tif err := json.Unmarshal(in.Data, &doc); err != nil { return err }\n\t\tif first == \"\" { first = doc.OpenAPI; continue }\n\t\tif doc.OpenAPI != first {\n\t\t\treturn fmt.Errorf(\"version mismatch: %q vs %q in %s\", first, doc.OpenAPI, in.Name)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if err := versionsMatch(inputs); err != nil {\n\treturn fmt.Errorf(\"pre-merge check: %w\", err)\n}\nmerged, err := merge.Merge(inputs)\nif err != nil { return err }","preventionTips":["Pin all protoc/generator invocations to the same OpenAPI output version","Migrate older 3.0.x specs before adding them to the merge set","Record the spec version in CI and fail fast on drift","Keep generator dependencies versioned identically across packages"],"tags":["openapi","versioning","merge-conflict"],"backgroundTag":"openapi-version-mismatch","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}