Skip to content

fix(api): let media uploads outlive the server-wide timeouts - #13

Merged
antoniolg merged 1 commit into
antoniolg:mainfrom
maximofn:fix/media-upload-timeout
Nov 5, 2026
Merged

antoniolg merged 1 commit into
antoniolg:mainfrom
maximofn:fix/media-upload-timeout

Conversation

@maximofn

@maximofn maximofn commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Problem

POST /media runs under the server-wide ReadTimeout of 15 s (cmd/postflow-server/main.go). In Go that timeout covers the whole request, body included, so any upload slower than 15 s is cut off. At 10 MB/s the real limit is about 150 MB, far below the documented 512 MiB.

Clients see a connection error, not a 413, so it looks like a network problem:

EOF occurred in violation of protocol (_ssl.c:2417)

Seen with real videos: every file from 157 MB to 3 GB failed after 15-16 s, while files up to 130 MB got through at about 9 MB/s. The limit moves with upload speed, which is why the same file can pass one day and fail the next.

Fix

Give this route a 15-minute window with http.ResponseController and keep the short timeouts for every other route.

  • handleUploadMedia extends the read and write deadlines. The write deadline matters too: WriteTimeout (30 s) would otherwise stop the response to any upload that took longer.
  • responseRecorder gets Unwrap(). Without it the controller can't reach the connection and the deadlines silently stay as they were.
  • README.md and docs/specs/openapi.yaml state the new limit.

Testing

  • Adds TestUploadMediaOutlivesServerTimeouts, which uploads through a real server with its timeouts scaled down.
  • Not run yet: I could not download the module dependencies in my environment, so neither this test nor go test ./... has run against this branch. Please rely on CI here.
  • I did check the mechanism with a standalone program using only the standard library and the same server shape. Without the fix the upload is cut off; with the deadlines but no Unwrap() it is still cut off; with both it completes in full.

Out of scope

  • A reverse proxy in front of the server may have its own limits, which would need raising separately.
  • MCP uploads (postflow_upload_media, base64 over /mcp) still run under the 15 s timeout.
  • Files above 512 MiB are still rejected. Chunked uploads remain on the roadmap in docs/specs/mvp.md.

https://claude.ai/code/session_01G9tsQQuw2iiBtGxGTp23qH

POST /media runs under the server's ReadTimeout (15 s), which in Go covers
the whole request, body included, plus a 30 s WriteTimeout. Any upload slower
than that is cut off: at 10 MB/s the real limit is about 150 MB, far below the
documented 512 MiB, and clients see a connection error instead of a 413.

Give this route a 15-minute window with http.ResponseController and keep the
short timeouts everywhere else. responseRecorder needs Unwrap so the controller
can reach the connection.

Claude-Session: https://claude.ai/code/session_01G9tsQQuw2iiBtGxGTp23qH
@antoniolg
antoniolg merged commit 066a35c into antoniolg:main Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants