{"record":{"id":"8f3326016b57e854","repo":"grpc-ecosystem/grpc-gateway","slug":"components-s-s-w","errorCode":null,"errorMessage":"components.%s.%s: %w","messagePattern":"components\\.(.+?)\\.(.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openapiv3-merge/internal/merge/merge.go","lineNumber":352,"sourceCode":"\t\t{\"requestBodies\", &dst.RequestBodies, &src.RequestBodies},\n\t\t{\"headers\", &dst.Headers, &src.Headers},\n\t\t{\"securitySchemes\", &dst.SecuritySchemes, &src.SecuritySchemes},\n\t\t{\"links\", &dst.Links, &src.Links},\n\t\t{\"callbacks\", &dst.Callbacks, &src.Callbacks},\n\t\t{\"pathItems\", &dst.PathItems, &src.PathItems},\n\t}\n\tfor _, p := range pairs {\n\t\tif len(*p.src) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif *p.dst == nil {\n\t\t\t*p.dst = make(map[string]json.RawMessage, len(*p.src))\n\t\t}\n\t\tfor k, v := range *p.src {\n\t\t\tif prev, dup := (*p.dst)[k]; dup {\n\t\t\t\tsame, err := canonicalEqual(prev, v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"components.%s.%s: %w\", p.name, k, err)\n\t\t\t\t}\n\t\t\t\tif !same {\n\t\t\t\t\treturn fmt.Errorf(\"components.%s.%q: %s redefines an entry with a different value\", p.name, k, srcName)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t(*p.dst)[k] = v\n\t\t}\n\t}\n\treturn nil\n}\n\n// mergeTags appends tags from src to out, deduplicating by `name`. Two tag\n// entries sharing a name must declare identical metadata.\nfunc mergeTags(out *document, seen map[string]json.RawMessage, src *document) error {\n\tfor _, raw := range src.Tags {\n\t\tname, err := tagName(raw)\n\t\tif err != nil {","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/openapiv3-merge/internal/merge/merge.go#L334-L370","documentation":"Raised in mergeComponents when two inputs define the same components/* sub-map key and canonicalEqual fails to canonicalize either value. It wraps the underlying canonicalization/decode error with the component kind and key. The value's raw JSON could not be re-encoded for comparison, indicating malformed nested content.","triggerScenarios":"Calling Merge where two documents share a component key (e.g. components.schemas.example.v1.User) and the raw value of one is invalid JSON that only fails when canonicalized during the merge comparison.","commonSituations":"Corrupted generator output inside a component definition, hand-edits that broke nested JSON in a duplicated schema, or binary-encoding mishaps when embedding raw JSON.","solutions":["Validate both input files with a JSON parser to locate the malformed component value","Fix or regenerate the document with the invalid component","Ensure any tooling that post-processes the files preserves valid JSON"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func componentsAreValidJSON(data []byte) error {\n\tvar doc struct { Components map[string]map[string]json.RawMessage `json:\"components\"` }\n\tif err := json.Unmarshal(data, &doc); err != nil { return err }\n\tfor kind, m := range doc.Components {\n\t\tfor k, v := range m {\n\t\t\tvar anyVal any\n\t\t\tif err := json.Unmarshal(v, &anyVal); err != nil {\n\t\t\t\treturn fmt.Errorf(\"components.%s.%s: invalid JSON: %w\", kind, k, err)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"for _, in := range inputs {\n\tif err := componentsAreValidJSON(in.Data); err != nil {\n\t\treturn fmt.Errorf(\"%s: %w\", in.Name, err)\n\t}\n}\nmerged, err := merge.Merge(inputs)","preventionTips":["Parse each input fully before merging to catch malformed component values","Avoid post-processing generated JSON with string tools","Validate components against the OpenAPI schema in CI"],"tags":["json","openapi","components"],"backgroundTag":"json-unmarshal-type-error","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}