{"record":{"id":"11e48ff1deec55eb","repo":"grpc-ecosystem/grpc-gateway","slug":"can-t-resolve-openapi-name-from-q","errorCode":null,"errorMessage":"can't resolve OpenAPI name from %q","messagePattern":"can't resolve OpenAPI name from %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoc-gen-openapiv2/internal/genopenapi/template.go","lineNumber":903,"sourceCode":"\t\t\tschema.AdditionalProperties = &openapiSchemaObject{}\n\t\t\tschema.Properties = &openapiSchemaObjectProperties{keyVal{\n\t\t\t\tKey:   \"@type\",\n\t\t\t\tValue: property.Value,\n\t\t\t}}\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc renderMessagesAsDefinition(messages messageMap, d openapiDefinitionsObject, reg *descriptor.Registry, customRefs refMap, pathParams []descriptor.Parameter) error {\n\t// Sort keys so that when two messages flatten to the same OpenAPI definition\n\t// name the winner is deterministic (last in sorted order wins) rather than\n\t// varying with Go's random map iteration order.\n\tfor _, name := range slices.Sorted(maps.Keys(messages)) {\n\t\tmsg := messages[name]\n\t\tswgName, ok := fullyQualifiedNameToOpenAPIName(msg.FQMN(), reg)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"can't resolve OpenAPI name from %q\", msg.FQMN())\n\t\t}\n\t\tif skipRenderingRef(name) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif opt := msg.GetOptions(); opt != nil && opt.MapEntry != nil && *opt.MapEntry {\n\t\t\tcontinue\n\t\t}\n\t\tif _, exists := d[swgName]; exists {\n\t\t\tgrpclog.Warningf(\"Collision: multiple messages map to OpenAPI definition name %q; the definition will be overwritten\", swgName)\n\t\t}\n\t\tvar err error\n\t\td[swgName], err = renderMessageAsDefinition(msg, reg, customRefs, pathParams)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil","sourceCodeStart":885,"sourceCodeEnd":921,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/protoc-gen-openapiv2/internal/genopenapi/template.go#L885-L921","documentation":"renderMessagesAsDefinition converts registered messages into OpenAPI definitions and must translate each message's fully-qualified name into the (possibly shortened, uniquified) OpenAPI schema name via fullyQualifiedNameToOpenAPIName. If the FQMN isn't found in the precomputed name map, generation fails with 'can't resolve OpenAPI name from %q'. It indicates the message-name resolution pass and the rendering pass saw inconsistent registry state.","triggerScenarios":"applyTemplate/addCustomRefs call renderMessagesAsDefinition over the collected messages map and fullyQualifiedNameToOpenAPIName(msg.FQMN(), reg) returns ok=false — the message was collected for rendering but its name was never registered during the FQMN→OpenAPI-name resolution (resolveFullyQualifiedNameToOpenAPINames) pass.","commonSituations":"Messages pulled in from dependency files processed inconsistently across multiple protoc runs; duplicate or conflicting package/file names breaking FQMN mapping; plugin bugs with unusual naming (deeply nested messages across packages) that the name-uniquifier skipped.","solutions":["Regenerate the full API surface in a single protoc invocation so all messages are registered in the FQMN name map.","Check for duplicate proto package/file names that collide in the OpenAPI name uniquifier.","Verify the message's package path is consistent (no mixed casing or path aliases) across imports.","Update protoc-gen-openapiv2 — this can stem from name-resolution bugs fixed in newer releases."],"exampleFix":"// before: two protos both declare package foo.v1 with the same file basenames in different dirs, breaking name resolution\n// after: make packages/files unique\n// a/types.proto -> package a.v1; b/types.proto -> package b.v1","handlingStrategy":"try-catch","validationCode":"// Ensure name resolution covers all messages before rendering:\nfor name := range messages {\n    if _, ok := fullyQualifiedNameToOpenAPIName(name, reg); !ok {\n        return fmt.Errorf(\"pre-check: %s missing from OpenAPI name table\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := generateOpenAPI(); err != nil {\n    if strings.Contains(err.Error(), \"can't resolve OpenAPI name\") {\n        return fmt.Errorf(\"regenerate with the FULL proto file set: %w\", err)\n    }\n    return err\n}","preventionTips":["Always generate docs from a single full-surface protoc run.","Keep proto packages and file paths unique to avoid name collisions.","Pin/upgrade protoc-gen-openapiv2 regularly for name-resolution fixes."],"tags":["codegen","openapi","name-resolution","fqmn"],"backgroundTag":"openapi-name-resolution-failed","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}