{"record":{"id":"270c1aa74c88633d","repo":"grpc-ecosystem/grpc-gateway","slug":"only-primitive-and-enum-types-are-allowed-in-repea","errorCode":null,"errorMessage":"only primitive and enum types are allowed in repeated path parameters","messagePattern":"only primitive and enum types are allowed in repeated path parameters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoc-gen-openapiv2/internal/genopenapi/template.go","lineNumber":1625,"sourceCode":"\t\t\t\t}\n\t\t\t\t// extract any constraints specified in the path placeholders into ECMA regular expressions\n\t\t\t\tpathParamRegexpMap := partsToRegexpMap(parts)\n\t\t\t\t// Keep track of path parameter overrides\n\t\t\t\tpathParamNames := make(map[string]string)\n\t\t\t\tfor _, parameter := range pathParams {\n\n\t\t\t\t\tvar paramType, paramFormat, desc, collectionFormat, schemaPattern string\n\t\t\t\t\tvar defaultValue interface{}\n\t\t\t\t\tvar example RawExample\n\t\t\t\t\tvar enumNames interface{}\n\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\"","sourceCodeStart":1607,"sourceCodeEnd":1643,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/protoc-gen-openapiv2/internal/genopenapi/template.go#L1607-L1643","documentation":"When rendering path parameters in the OpenAPI output, renderServices checks each parameter's field type. A repeated (list) path parameter whose field is a GROUP or MESSAGE type is rejected unless it is a well-known type, because a repeated message cannot be represented as a single OpenAPI path parameter. The generator returns this error instead of emitting an invalid spec.","triggerScenarios":"A proto method path binding (google.api.http) that puts a repeated message field into the URL path template, e.g. `post: \"/v1/{itemsFoo=**}\"` where `items` is `repeated Foo` and Foo is a message (and not a well-known type).","commonSituations":"Designing HTTP bindings that inline repeated sub-message fields in paths; copying a binding pattern from a repeated string path param and applying it to a message type; upgrading grpc-gateway after stricter validation was added.","solutions":["Change the path template so it only references primitive/enum leaf fields, e.g. `{item_id}` for `repeated string item_id`, not a whole repeated message.","Restructure the binding to pass the repeated message in the request body instead of the path.","If you only need some fields, flatten them into repeated primitive fields and reference those in the path.","If the field is a well-known type wrapper, verify descriptor.IsWellKnownType applies; otherwise convert to a primitive/enum."],"exampleFix":"// before\noption (google.api.http) = { post: \"/v1/{foos=**}\" body: \"*\" }; // repeated Foo foos\n// after\noption (google.api.http) = { post: \"/v1/{ids=**}\" body: \"*\" }; // repeated string ids","handlingStrategy":"validation","validationCode":"// before generation, check repeated message fields are not used in path templates\nfor _, m := range svc.Methods {\n    for _, b := range m.Bindings {\n        for _, p := range b.PathParams {\n            if p.IsRepeated() && p.Target.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE && !descriptor.IsWellKnownType(p.Target.GetTypeName()) {\n                return fmt.Errorf(\"path param %s is a repeated message; use a primitive/enum field\", p.Target.GetName())\n            }\n        }\n    }\n}","typeGuard":"func validRepeatedPathParam(f *descriptor.Field) bool {\n    return !f.IsRepeated() || f.Target.GetType() != descriptorpb.FieldDescriptorProto_TYPE_MESSAGE || descriptor.IsWellKnownType(f.Target.GetTypeName())\n}","tryCatchPattern":"if err := applyTemplate(...); err != nil {\n    if strings.Contains(err.Error(), \"repeated path parameters\") {\n        return fmt.Errorf(\"fix google.api.http binding: %w\", err)\n    }\n    return err\n}","preventionTips":["Only reference scalar leaf fields in HTTP path templates.","Pass repeated messages via the request body, not the URL path.","Run protoc-gen-openapiv2 in CI to catch invalid bindings before release."],"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"}