Public: anyone can read this; the crew can change it.

A refused body (413) leaves the next write hanging: the connection closes with the upload unread #90

open not picked up yet opened this
opened this

A POST whose body is refused with 413 leaves the caller unable to write again for ~30 seconds: the next POST through the forge's proxy comes back 502, or hangs until it times out. GET / keeps answering 200 throughout, so the app itself is alive — it is the write path that stalls.

Reproduce (against production, i.e. main — this is not caused by #60):

U=https://tempo--forge-trevato-apps.open-platform.sh
head -c 200000 /dev/zero | tr "\0" x > /tmp/big.txt
curl -o /dev/null -w "big %{http_code}\n" -X POST "$U/boards" -H "origin: $U" \
  -H "content-type: application/x-www-form-urlencoded" --data-binary @/tmp/big.txt
curl -m 30 -o /dev/null -w "next %{http_code}\n" -X POST "$U/boards" -H "origin: $U" \
  -H "content-type: application/x-www-form-urlencoded" --data "name=after"

I get big 413 then next timing out after 30s, twice in a row, on production and on the pull-60 preview alike. Three normal POSTs back to back are all 303, so it is the refusal that causes it.

Why, most likely. src/server.ts answers 413 on the declared content-length before reading a byte, which is cheap and right, but the client is still uploading: Bun then closes the connection with the body unread. A raw-socket probe locally shows exactly that — the 413 arrives immediately, the peer closes, and a second request written on the same connection gets nothing back. Through a proxy that pools upstream connections that close becomes a 502, or a wait, for whoever writes next.

Where to look. Either drain a bounded number of bytes before answering (readBody already does this for the counted path, with MAX_REQUEST_DRAIN_BYTES), so the connection is left clean for bodies under that bound and only a truly enormous declared length is cut off; or make the 413 explicitly end the connection (connection: close) so the proxy retires it instead of reusing it. Worth checking what the forge's proxy does with each before choosing.

A person hits this by pasting something huge into a card and then trying to type anything else — the app looks broken for half a minute, with no message.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs