google/tsunami-security-scanner · error · ValueError

A request body is not allowed for HTTP GET/HEAD request.

Error message

A request body is not allowed for HTTP GET/HEAD request.

What it means

HttpRequest.Builder.build() enforces that GET and HEAD requests carry no body, per the HTTP specification. If a body was set on a GET/HEAD builder, ValueError is raised at build time rather than producing a request that servers would reject or misinterpret.

Solutions

  1. Change the HTTP method to POST/PUT/PATCH if a body is genuinely required
  2. Move the data into the URL query string for GET requests (params, not body)
  3. Skip body assignment when method is GET/HEAD
  4. Reorder builder calls so the method is set first and gate body-setting on it

Example fix

// before
builder.set_method(HttpMethod.GET).set_body(data)
return builder.build()  # raises
// after
if data:
  builder.set_method(HttpMethod.POST).set_body(data)
else:
  builder.set_method(HttpMethod.GET)
return builder.build()
Defensive patterns

Strategy: validation

Validate before calling

def build_safe(builder, method, body=None):
    if method in (HttpMethod.GET, HttpMethod.HEAD):
        body = None
    if body:
        builder.set_body(body)
    builder.set_method(method)
    return builder.build()

Try / catch

try:
    return builder.build()
except ValueError as e:
    if 'GET/HEAD' in str(e):
        logging.error('Body set on %s request', builder.http_request.method)
    raise

Prevention

When it happens

Trigger: Calling set_body(...) (or equivalent) on a builder whose method is GET or HEAD, then calling build(); commonly the method defaults to GET and body-setting code runs unconditionally.

Common situations: Code that always attaches a POST-style JSON body but the method was changed/derived to GET; passing query parameters as a body instead of the URL query string; shared request-building helpers that ignore the method.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of google/tsunami-security-scanner@363ba87b35 (2026-09-13). Data as JSON: /api/errors/5caa2366335b3f65. Report an issue: GitHub.

Appendix: source

Thrown at plugin_server/py/common/net/http/http_request.py:108

    return self

  def set_request_body(self, request_body: Optional[bytes] = None) -> 'Builder':
    """Set the request body."""
    self.http_request.body = request_body
    return self

  def with_empty_headers(self) -> 'Builder':
    """Set an empty Http_headers for the request."""
    self.set_headers(HttpHeadersBuilder().build())
    return self

  def build(self) -> 'HttpRequest':
    if (
        self.http_request.method == HttpMethod.GET
        or self.http_request.method == HttpMethod.HEAD
    ):
      if self.http_request.body:
        raise ValueError(
            'A request body is not allowed for HTTP GET/HEAD request.')
    return self.http_request

View on GitHub (pinned to 363ba87b35)