grpc-ecosystem/grpc-gateway · error
only primitive and enum types are allowed in repeated path p
Error message
only primitive and enum types are allowed in repeated path parameters
What it means
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.
Source
Thrown at protoc-gen-openapiv2/internal/genopenapi/template.go:1625
}
// extract any constraints specified in the path placeholders into ECMA regular expressions
pathParamRegexpMap := partsToRegexpMap(parts)
// Keep track of path parameter overrides
pathParamNames := make(map[string]string)
for _, parameter := range pathParams {
var paramType, paramFormat, desc, collectionFormat, schemaPattern string
var defaultValue interface{}
var example RawExample
var enumNames interface{}
var items *openapiItemsObject
var minItems *int
var extensions []extension
switch pt := parameter.Target.GetType(); pt {
case descriptorpb.FieldDescriptorProto_TYPE_GROUP, descriptorpb.FieldDescriptorProto_TYPE_MESSAGE:
if descriptor.IsWellKnownType(parameter.Target.GetTypeName()) {
if parameter.IsRepeated() {
return errors.New("only primitive and enum types are allowed in repeated path parameters")
}
schema := schemaOfField(parameter.Target, reg, customRefs)
paramType = schema.Type
paramFormat = schema.Format
desc = schema.Description
defaultValue = schema.Default
example = schema.Example
schemaPattern = schema.Pattern
extensions = schema.extensions
} else {
return errors.New("only primitive and well-known types are allowed in path parameters")
}
case descriptorpb.FieldDescriptorProto_TYPE_ENUM:
enum, err := reg.LookupEnum("", parameter.Target.GetTypeName())
if err != nil {
return err
}
paramType = "string"View on GitHub (pinned to a58a4436a3)
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.
Example fix
// before
option (google.api.http) = { post: "/v1/{foos=**}" body: "*" }; // repeated Foo foos
// after
option (google.api.http) = { post: "/v1/{ids=**}" body: "*" }; // repeated string ids Defensive patterns
Strategy: validation
Validate before calling
// before generation, check repeated message fields are not used in path templates
for _, m := range svc.Methods {
for _, b := range m.Bindings {
for _, p := range b.PathParams {
if p.IsRepeated() && p.Target.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE && !descriptor.IsWellKnownType(p.Target.GetTypeName()) {
return fmt.Errorf("path param %s is a repeated message; use a primitive/enum field", p.Target.GetName())
}
}
}
} Type guard
func validRepeatedPathParam(f *descriptor.Field) bool {
return !f.IsRepeated() || f.Target.GetType() != descriptorpb.FieldDescriptorProto_TYPE_MESSAGE || descriptor.IsWellKnownType(f.Target.GetTypeName())
} Try / catch
if err := applyTemplate(...); err != nil {
if strings.Contains(err.Error(), "repeated path parameters") {
return fmt.Errorf("fix google.api.http binding: %w", err)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- only primitive and well-known types are allowed in path para
- no target service defined in the file
- unexpected number of yaml nodes
- encountered object type with a summary, but no description
- no description nor summary property
AI-assisted analysis of grpc-ecosystem/grpc-gateway@a58a4436a3 (2026-09-02).
Data as JSON: /api/errors/270c1aa74c88633d.
Report an issue: GitHub.