grpc-ecosystem/grpc-gateway · error

must not set request body when http method is GET: %s

Error message

must not set request body when http method is GET: %s

What it means

HTTP GET requests carry parameters only in the URL; the generator rejects google.api.http 'get' rules that also declare a 'body'. A GET with a body is not valid HTTP semantics, so template building fails with the method descriptor name.

Source

Thrown at internal/descriptor/services.go:108

	}
	meth := &Method{
		Service:               svc,
		MethodDescriptorProto: md,
		RequestType:           requestType,
		ResponseType:          responseType,
	}

	newBinding := func(opts *options.HttpRule, idx int) (*Binding, error) {
		var (
			httpMethod   string
			pathTemplate string
		)
		switch {
		case opts.GetGet() != "":
			httpMethod = "GET"
			pathTemplate = opts.GetGet()
			if opts.Body != "" {
				return nil, fmt.Errorf("must not set request body when http method is GET: %s", md.GetName())
			}

		case opts.GetPut() != "":
			httpMethod = "PUT"
			pathTemplate = opts.GetPut()

		case opts.GetPost() != "":
			httpMethod = "POST"
			pathTemplate = opts.GetPost()

		case opts.GetDelete() != "":
			httpMethod = "DELETE"
			pathTemplate = opts.GetDelete()
			if opts.Body != "" && !r.allowDeleteBody {
				return nil, fmt.Errorf("must not set request body when http method is DELETE except allow_delete_body option is true: %s", md.GetName())
			}

		case opts.GetPatch() != "":

View on GitHub (pinned to a58a4436a3)

Solutions

  1. Remove the 'body' field from the google.api.http GET annotation
  2. Pass parameters via the path template and query parameters instead
  3. If a request body is truly required, switch the rpc to POST or PUT
  4. Keep GET to a single request field mapped into the URL

Example fix

// before
option (google.api.http) = { get: "/v1/books/{id}" body: "*" };
// after
option (google.api.http) = { get: "/v1/books/{id}" };
Defensive patterns

Strategy: validation

Validate before calling

if rule.GetGet() != "" && rule.GetBody() != "" {
    return fmt.Errorf("rpc %s: GET rule must not declare body", rpc.GetName())
}
err := buildTemplates(rpc)

Prevention

When it happens

Trigger: A rpc's google.api.http option sets both 'get' and 'body' fields; building the template for such a method raises this error immediately when opts.Body != "" under the GetGet() branch.

Common situations: Hand-editing annotations and leaving a 'body: "*"' from a copied PUT/POST rule; tools migrating POST to GET that keep the body field; misunderstandings about GET semantics for large payloads.

Related errors


AI-assisted analysis of grpc-ecosystem/grpc-gateway@a58a4436a3 (2026-09-02). Data as JSON: /api/errors/daa92a4043b128ed. Report an issue: GitHub.