{"record":{"id":"7a1fa4da1d718248","repo":"grpc-ecosystem/grpc-gateway","slug":"failed-to-lookup-message-type-s-w","errorCode":null,"errorMessage":"failed to lookup message type %s: %w","messagePattern":"failed to lookup message type (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoc-gen-grpc-gateway/internal/gengateway/template.go","lineNumber":66,"sourceCode":"\treturn \"\", errors.New(\"no body field found\")\n}\n\n// GetBodyFieldType returns the Go type of the body field.\nfunc (b binding) GetBodyFieldType() (string, error) {\n\tif b.Body == nil || len(b.Body.FieldPath) == 0 {\n\t\treturn \"\", errors.New(\"no body field found\")\n\t}\n\n\tlastComponent := b.Body.FieldPath[len(b.Body.FieldPath)-1]\n\tfieldType := lastComponent.Target.GetType()\n\n\t// Handle message types\n\tif fieldType == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE {\n\t\t// Get the parent message to provide proper lookup context\n\t\tparentMsg := lastComponent.Target.Message\n\t\tmsg, err := b.Registry.LookupMsg(parentMsg.FQMN(), lastComponent.Target.GetTypeName())\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to lookup message type %s: %w\", lastComponent.Target.GetTypeName(), err)\n\t\t}\n\t\treturn msg.GoType(b.Method.Service.File.GoPkg.Path), nil\n\t}\n\n\treturn \"\", errors.New(\"unsupported body field type\")\n}\n\n// HasQueryParam determines if the binding needs parameters in query string.\n//\n// It sometimes returns true even though actually the binding does not need.\n// But it is not serious because it just results in a small amount of extra codes generated.\nfunc (b binding) HasQueryParam() bool {\n\tif b.Body != nil && len(b.Body.FieldPath) == 0 {\n\t\treturn false\n\t}\n\tfields := make(map[string]bool)\n\tfor _, f := range b.Method.RequestType.Fields {\n\t\tfields[f.GetName()] = true","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/protoc-gen-grpc-gateway/internal/gengateway/template.go#L48-L84","documentation":"In protoc-gen-grpc-gateway's body-field type resolution (GetBodyFieldType), when a body mapping path component targets a message-typed field, the registry is asked to resolve that type name relative to the parent message. If LookupMsg cannot find the message (unregistered file, wrong name, load-order issue), the code wraps the failure with 'failed to lookup message type %s: %w'. It signals the proto descriptor graph is incomplete or inconsistent for the body path being generated.","triggerScenarios":"Calling GetBodyFieldType (during gateway template execution) when lastComponent.Target is TYPE_MESSAGE and Registry.LookupMsg(parentMsg.FQMN(), typeName) fails — e.g. the message's file was never loaded into the Registry, the type name is stale, or external deps weren't imported via WithImportPath/LoadFromPlugin.","commonSituations":"Generating a gateway for protos that depend on external packages (googleapis annotations, well-known types) without registering those dependency files; renaming/moving a message so body path references no longer resolve; using a plugin version mismatched with regenerated descriptors.","solutions":["Ensure every proto dependency (including transitive ones) is passed to protoc so its descriptors are registered with the Registry before generation.","Regenerate descriptors so the body path's message type name matches the current proto (check lastComponent.Target.GetTypeName() against your .proto files).","If using RegisterFunc/registry loading, verify LookupMsg-able messages exist — e.g. confirm the message FQMN appears in the registry with a small debug print or registry lookup in a custom plugin.","Update protoc-gen-grpc-gateway to match your protoc/protoc-gen-go versions and regenerate."],"exampleFix":"// before: protoc foo.proto only, message Bar lives in bar.proto used as body field\nprotoc --grpc-gateway_out=. foo.proto\n\n// after: pass all deps\nprotoc -I . --grpc-gateway_out=. foo.proto bar.proto","handlingStrategy":"validation","validationCode":"// In a custom plugin/wrapper, before generating:\nfor _, dep := range allProtoFiles {\n    if _, err := reg.LookupMsg(parentFQMN, typeName); err != nil {\n        return fmt.Errorf(\"missing message %s (from %s): %w\", typeName, dep, err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass all transitive proto dependencies to protoc.","Regenerate gateway code and descriptors together in CI.","Keep protoc-gen-grpc-gateway version aligned with protoc/protobuf runtime."],"tags":["codegen","proto-registry","grpc-gateway","descriptor-lookup"],"backgroundTag":"proto-message-not-found","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}