{"record":{"id":"da201566cec99a4a","repo":"grpc-ecosystem/grpc-gateway","slug":"only-primitive-and-well-known-types-are-allowed-in","errorCode":null,"errorMessage":"only primitive and well-known types are allowed in path parameters","messagePattern":"only primitive and well-known types are allowed in path parameters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoc-gen-openapiv2/internal/genopenapi/template.go","lineNumber":1636,"sourceCode":"\t\t\t\t\tvar items *openapiItemsObject\n\t\t\t\t\tvar minItems *int\n\t\t\t\t\tvar extensions []extension\n\t\t\t\t\tswitch pt := parameter.Target.GetType(); pt {\n\t\t\t\t\tcase descriptorpb.FieldDescriptorProto_TYPE_GROUP, descriptorpb.FieldDescriptorProto_TYPE_MESSAGE:\n\t\t\t\t\t\tif descriptor.IsWellKnownType(parameter.Target.GetTypeName()) {\n\t\t\t\t\t\t\tif parameter.IsRepeated() {\n\t\t\t\t\t\t\t\treturn errors.New(\"only primitive and enum types are allowed in repeated path parameters\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tschema := schemaOfField(parameter.Target, reg, customRefs)\n\t\t\t\t\t\t\tparamType = schema.Type\n\t\t\t\t\t\t\tparamFormat = schema.Format\n\t\t\t\t\t\t\tdesc = schema.Description\n\t\t\t\t\t\t\tdefaultValue = schema.Default\n\t\t\t\t\t\t\texample = schema.Example\n\t\t\t\t\t\t\tschemaPattern = schema.Pattern\n\t\t\t\t\t\t\textensions = schema.extensions\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn errors.New(\"only primitive and well-known types are allowed in path parameters\")\n\t\t\t\t\t\t}\n\t\t\t\t\tcase descriptorpb.FieldDescriptorProto_TYPE_ENUM:\n\t\t\t\t\t\tenum, err := reg.LookupEnum(\"\", parameter.Target.GetTypeName())\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tparamType = \"string\"\n\t\t\t\t\t\tparamFormat = \"\"\n\t\t\t\t\t\tenumNames = listEnumNames(reg, enum)\n\t\t\t\t\t\tif reg.GetEnumsAsInts() {\n\t\t\t\t\t\t\tparamType = \"integer\"\n\t\t\t\t\t\t\tparamFormat = \"\"\n\t\t\t\t\t\t\tenumNames = listEnumNumbers(reg, enum)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tschema := schemaOfField(parameter.Target, reg, customRefs)\n\t\t\t\t\t\tdesc = schema.Description\n\t\t\t\t\t\tdefaultValue = schema.Default","sourceCodeStart":1618,"sourceCodeEnd":1654,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/protoc-gen-openapiv2/internal/genopenapi/template.go#L1618-L1654","documentation":"renderServices requires that path parameters be primitive types, enums, or protobuf well-known types. When a non-repeated path parameter targets a GROUP or MESSAGE field that is not a well-known type (e.g. google.protobuf.Timestamp, wrappers), the generator returns \"only primitive and well-known types are allowed in path parameters\" because such a message cannot be rendered as a valid OpenAPI path parameter.","triggerScenarios":"A google.api.http path template referencing a message-typed field that is not a well-known type, e.g. `get: \"/v1/{book.title}\"` where the referenced field is a custom message, or a group field in the path.","commonSituations":"Pointing a path variable at a nested message/submessage instead of a scalar; using proto2 groups; copying bindings from another service whose field was a well-known wrapper; protos not importing google/protobuf/wrappers.proto or timestamp.proto so the field is a custom message.","solutions":["Reference a primitive or enum field in the path template instead of the message, e.g. `{book_id}` where book_id is int64/string, or `{book.id}` for a scalar subfield.","Move the message field out of the path into the request body (`body: \"*\"` or a body field).","If you intended a wrapper, use the actual well-known type (google.protobuf.StringValue, Timestamp, etc.) that IsWellKnownType recognizes.","For IDs, flatten them: put `string id` on the request message and bind `{id}` in the path."],"exampleFix":"// before\nrpc GetBook(BookRequest) ... // path: \"/v1/{book=**}\" where book is message Book\n// after\nrpc GetBook(GetBookRequest) ... // message { string book_id = 1; } path: \"/v1/{book_id}\"","handlingStrategy":"validation","validationCode":"for _, p := range binding.PathParams {\n    t := p.Target.GetType()\n    if (t == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE || t == descriptorpb.FieldDescriptorProto_TYPE_GROUP) && !descriptor.IsWellKnownType(p.Target.GetTypeName()) {\n        return fmt.Errorf(\"path param %q must be a primitive, enum, or well-known type\", p.Target.GetName())\n    }\n}","typeGuard":"func validPathParam(f *descriptor.Field) bool {\n    switch f.Target.GetType() {\n    case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, descriptorpb.FieldDescriptorProto_TYPE_GROUP:\n        return descriptor.IsWellKnownType(f.Target.GetTypeName())\n    default:\n        return true\n    }\n}","tryCatchPattern":"if err := applyTemplate(...); err != nil {\n    if strings.Contains(err.Error(), \"well-known types are allowed in path parameters\") {\n        return fmt.Errorf(\"rewrite the http rule path to use a scalar field: %w\", err)\n    }\n    return err\n}","preventionTips":["Bind path variables only to primitive/enum fields or explicit subfields like {msg.id}.","Avoid proto2 groups in HTTP bindings entirely.","Review google.api.http annotations during proto code review."],"tags":["openapi","protobuf","path-parameters","code-generation"],"backgroundTag":"invalid-path-parameter-type","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}