{"record":{"id":"a86de4423553a46b","repo":"grpc-ecosystem/grpc-gateway","slug":"s-s-w","errorCode":null,"errorMessage":"%s.%s: %w","messagePattern":"%s\\.%s: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openapiv3-merge/internal/merge/merge.go","lineNumber":309,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\tif err := mergeSecurity(out, d); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tmergeExtras(out.extras, d.extras)\n\t}\n\treturn out, nil\n}\n\n// mergeOrdered appends entries from src into dst, rejecting key collisions\n// whose values differ canonically.\nfunc mergeOrdered(field string, dst, src *orderedObject, srcName string) error {\n\tfor _, k := range src.keys {\n\t\tv := src.vals[k]\n\t\tif existing, ok := dst.get(k); ok {\n\t\t\tsame, err := canonicalEqual(existing, v)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%s.%s: %w\", field, k, err)\n\t\t\t}\n\t\t\tif !same {\n\t\t\t\treturn fmt.Errorf(\"%s.%q: %s redefines an entry with a different value\", field, k, srcName)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tdst.set(k, v)\n\t}\n\treturn nil\n}\n\n// mergeComponents unions each components/* sub-map. Same-named entries\n// across inputs must be canonically identical. The sub-maps are walked in\n// spec order so error messages are deterministic.\nfunc mergeComponents(dst, src *components, srcName string) error {\n\tpairs := []struct {\n\t\tname string\n\t\tdst  *map[string]json.RawMessage","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/openapiv3-merge/internal/merge/merge.go#L291-L327","documentation":"Raised in mergeOrdered while unioning `paths` (or `webhooks`) when canonicalEqual fails to canonicalize a duplicate key's value. It wraps the underlying canonicalization/JSON decode error with the field and key. This means two inputs share the same key but the raw value could not be parsed for comparison (e.g. invalid JSON inside the value).","triggerScenarios":"Calling Merge where two documents define the same path key and canonicalize() hits a JSON decode error on either value — essentially malformed raw JSON captured during parse but not decoded until comparison.","commonSituations":"Malformed nested values produced by a broken generator, corrupted file bytes inside a path object, or hand-patched JSON with subtle syntax errors in duplicated entries.","solutions":["Validate both input files fully with a JSON parser to find the malformed value","Fix or regenerate the document containing the invalid path value","Check for encoding corruption (BOM, truncated bytes) in the file"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func pathsAreValidJSON(data []byte) error {\n\tvar doc struct { Paths map[string]json.RawMessage `json:\"paths\"` }\n\tif err := json.Unmarshal(data, &doc); err != nil { return err }\n\tfor k, v := range doc.Paths {\n\t\tvar anyVal any\n\t\tif err := json.Unmarshal(v, &anyVal); err != nil {\n\t\t\treturn fmt.Errorf(\"paths.%s: invalid JSON: %w\", k, err)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"for _, in := range inputs {\n\tif err := pathsAreValidJSON(in.Data); err != nil {\n\t\treturn fmt.Errorf(\"%s: %w\", in.Name, err)\n\t}\n}\nmerged, err := merge.Merge(inputs)","preventionTips":["Fully parse each input before merging to flush out malformed nested values","Avoid hand-editing generated path objects","Detect file corruption (truncation, encoding issues) at load time","Re-run the generator rather than patching raw JSON"],"tags":["json","openapi","merge"],"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"}