{"record":{"id":"c7c6cd8ff06b73fe","repo":"grpc-ecosystem/grpc-gateway","slug":"must-not-set-request-body-when-http-method-is-dele","errorCode":null,"errorMessage":"must not set request body when http method is DELETE except allow_delete_body option is true: %s","messagePattern":"must not set request body when http method is DELETE except allow_delete_body option is true: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/descriptor/services.go","lineNumber":123,"sourceCode":"\t\t\thttpMethod = \"GET\"\n\t\t\tpathTemplate = opts.GetGet()\n\t\t\tif opts.Body != \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"must not set request body when http method is GET: %s\", md.GetName())\n\t\t\t}\n\n\t\tcase opts.GetPut() != \"\":\n\t\t\thttpMethod = \"PUT\"\n\t\t\tpathTemplate = opts.GetPut()\n\n\t\tcase opts.GetPost() != \"\":\n\t\t\thttpMethod = \"POST\"\n\t\t\tpathTemplate = opts.GetPost()\n\n\t\tcase opts.GetDelete() != \"\":\n\t\t\thttpMethod = \"DELETE\"\n\t\t\tpathTemplate = opts.GetDelete()\n\t\t\tif opts.Body != \"\" && !r.allowDeleteBody {\n\t\t\t\treturn nil, fmt.Errorf(\"must not set request body when http method is DELETE except allow_delete_body option is true: %s\", md.GetName())\n\t\t\t}\n\n\t\tcase opts.GetPatch() != \"\":\n\t\t\thttpMethod = \"PATCH\"\n\t\t\tpathTemplate = opts.GetPatch()\n\n\t\tcase opts.GetCustom() != nil:\n\t\t\tcustom := opts.GetCustom()\n\t\t\thttpMethod = custom.Kind\n\t\t\tpathTemplate = custom.Path\n\n\t\tdefault:\n\t\t\tif grpclog.V(1) {\n\t\t\t\tgrpclog.Infof(\"No pattern specified in google.api.HttpRule: %s\", md.GetName())\n\t\t\t}\n\t\t\treturn nil, nil\n\t\t}\n","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/internal/descriptor/services.go#L105-L141","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Remove the 'body' field from the DELETE annotation and pass identifiers via the path template","If a body is genuinely required, enable the allow_delete_body generator option","Replace the rpc with a POST-based bulk action (e.g. '/v1/items:batchDelete')","Align the annotation with REST conventions: DELETE targets identified by path"],"exampleFix":"// before\noption (google.api.http) = { delete: \"/v1/items\" body: \"*\" };\n// after\noption (google.api.http) = { post: \"/v1/items:batchDelete\" body: \"*\" };","handlingStrategy":"validation","validationCode":"if rule.GetDelete() != \"\" && rule.GetBody() != \"\" && !allowDeleteBody {\n    return fmt.Errorf(\"rpc %s: DELETE with body requires allow_delete_body\", rpc.GetName())\n}\nerr := buildTemplates(rpc)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer path-parameter-based DELETE; reserve bodies for POST bulk endpoints","If you must send a DELETE body, explicitly enable allow_delete_body in your generation flags and document why","Add a lint rule rejecting 'delete' annotations containing 'body'"],"tags":["http","annotation","protobuf","validation"],"backgroundTag":"delete-request-with-body","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}