Skip to content

Body-size limit returns misleading 400 instead of documented 413 on chunked/streaming bodies #272

Description

@richardmhope

Summary

The body-size limit middleware documents a 413 on oversized bodies. For the declared-Content-Length path this is correct and short-circuits inner middleware. But on the chunked/streaming path (no Content-Length), receive_guarded raises _BodyTooLarge while the endpoint is reading the body — and FastAPI wraps await request.body() / request.form() in a broad except Exception, converting it to HTTPException(400, "There was an error parsing the body"). The exception never reaches the middleware's except _BodyTooLarge (src/iceberg/auth/body_limit.py:61-83); the client gets 400, not 413.

Reproduced empirically: a 2 MB chunked (no Content-Length) POST to a pydantic-body endpoint behind this middleware → 400 {"detail":"There was an error parsing the body"}; the declared-length path correctly gives 413.

Impact

The DoS goal still holds (buffering stops at cap + one chunk), so this is a contract/correctness defect, not a security hole: the module docstring (body_limit.py:12-14) and the 413 contract are wrong for the streaming path, and the 400 is actively misleading to clients (implies malformed body, not oversized).

Why the suite misses it

tests/test_body_limit.py:23 builds a bare Starlette app — the one framework path the middleware actually protects in production (FastAPI) is untested.

Suggested fix

Signal the condition out-of-band rather than relying on exception propagation through FastAPI — e.g. set scope["iceberg.body_too_large"] = True and rewrite the response in send_tracked, or intercept the parse failure. Add an integration test through the real create_app() stack (bonus: assert the 413 carries the security headers, which is the stated reason for the middleware's position).

Found in Fable review of PR #232 → HEAD.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfable-reviewCorrectness findings from Claude Fable code reviewpriority: mediumImportant, not blocking

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions