grpc-ecosystem/grpc-gateway · error

must not set request body when http method is DELETE except

Error message

must not set request body when http method is DELETE except allow_delete_body option is true: %s

What it means

DELETE with a request body is discouraged and not supported by default; the generator only allows a 'body' on a 'delete' rule when the allow_delete_body option is explicitly enabled. Otherwise template building fails with the method descriptor name.

Source

Thrown at internal/descriptor/services.go:123

			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() != "":
			httpMethod = "PATCH"
			pathTemplate = opts.GetPatch()

		case opts.GetCustom() != nil:
			custom := opts.GetCustom()
			httpMethod = custom.Kind
			pathTemplate = custom.Path

		default:
			if grpclog.V(1) {
				grpclog.Infof("No pattern specified in google.api.HttpRule: %s", md.GetName())
			}
			return nil, nil
		}

View on GitHub (pinned to a58a4436a3)

Solutions

  1. Remove the 'body' field from the DELETE annotation and pass identifiers via the path template
  2. If a body is genuinely required, enable the allow_delete_body generator option
  3. Replace the rpc with a POST-based bulk action (e.g. '/v1/items:batchDelete')
  4. Align the annotation with REST conventions: DELETE targets identified by path

Example fix

// before
option (google.api.http) = { delete: "/v1/items" body: "*" };
// after
option (google.api.http) = { post: "/v1/items:batchDelete" body: "*" };
Defensive patterns

Strategy: validation

Validate before calling

if rule.GetDelete() != "" && rule.GetBody() != "" && !allowDeleteBody {
    return fmt.Errorf("rpc %s: DELETE with body requires allow_delete_body", rpc.GetName())
}
err := buildTemplates(rpc)

Prevention

When it happens

Trigger: A rpc's google.api.http option sets both 'delete' and a non-empty 'body', while Registry.allowDeleteBody is false (the default, set via CLI flag).

Common situations: Copy-pasting a POST annotation and changing only the verb to delete; bulk-delete rpcs that want a body; teams unaware that the generator requires an opt-in flag for this nonstandard pattern.

Related errors


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