Skip to content

fix(api): /stacks/new invalid_form message uses real 50 MiB cap, not 200 MB (B7-P1-1)#208

Merged
mastermanas805 merged 3 commits into
masterfrom
fix/api-stack-200mb-lie-2026-05-30
May 30, 2026
Merged

fix(api): /stacks/new invalid_form message uses real 50 MiB cap, not 200 MB (B7-P1-1)#208
mastermanas805 merged 3 commits into
masterfrom
fix/api-stack-200mb-lie-2026-05-30

Conversation

@mastermanas805

Copy link
Copy Markdown
Member

Summary

POST /stacks/new advertised a fake 200 MB upload cap in its invalid_form error message. Real cap is the global Fiber BodyLimit = 50 MiB set in router.go:169; anything > 50 MiB is rejected upstream by Fiber's ErrorHandler with payload_too_large and never reaches the handler. An agent that read the 200 MB hint and built a 100 MB tarball got 413 payload_too_large instead of the promised 400 invalid_form. One limit, two truths.

/deploy/new correctly says "max 50 MB" — this PR reconciles stack.go with deploy.go and the router-level ground truth.

Files changed

  • api/internal/handlers/stack.go — message + comment now reference the real 50 MiB aggregate cap, with a back-link to T19 P1-2 (where the global BodyLimit landed) and to this fix.
  • api/internal/handlers/upload_size_message_test.go (new) — registry-iterating regression test (rule 18) that walks every multipart-upload endpoint emitting invalid_form (deploy.New + stack.New today), drives each to that arm, and asserts the message references 50 (MiB|MB) and contains none of 200 MB, 200MB, 100 MB, 1 GB, etc.

Test plan

Local — DB-backed:

$ TEST_DATABASE_URL=postgres://... go test ./internal/handlers/ \
    -run 'TestUploadSizeMessage|TestStackNewFinal3_InvalidForm|TestDeployNewFinal3_InvalidForm|TestStackFinal' \
    -count=1 -short -timeout 120s
ok  	instant.dev/internal/handlers	1.994s

Test catches the bug — verified by reverting stack.go and re-running:

--- FAIL: TestUploadSizeMessage_NoLies (0.08s)
    --- FAIL: TestUploadSizeMessage_NoLies//stacks/new (0.00s)
        \"Request must be multipart/form-data (max 200 MB)\" should not contain \"200 MB\"
        invalid_form message must reference the real 50 MiB cap; got: \"Request must be multipart/form-data (max 200 MB)\"

Re-applying the fix returns ok.

Rule-17 coverage block

Symptom:        invalid_form message advertises wrong upload cap (200 MB)
Enumeration:    rg -n '200 MB|200MB|max 200|200 MiB' internal/handlers/
Sites found:    1  (stack.go:474,478)
Sites touched:  1  (stack.go same range)
Coverage test:  TestUploadSizeMessage_NoLies — iterates deploy.New + stack.New
                drivers; fails on any wrong-size literal or missing 50 MiB hint
Live verified:  pending merge + deploy → `curl POST /stacks/new -H'Content-Type:
                application/json' -d '{}'` against api.instanode.dev; expect
                400 + message referencing 50 MiB

Discipline checklist

  • Local go test returned literal ok before push
  • Test verified to FAIL pre-fix (sanity check)
  • Registry-iterating coverage (not a hand-typed slice)
  • No metrics/alerts introduced (rule 25 N/A — string-only change)
  • No OpenAPI / contract surface impact (message body only, error code + status unchanged)
  • Branch + remote confirmed before push (fix/api-stack-200mb-lie-2026-05-30origin/master)

Surface check (rule 22)

  • api/internal/handlers/stack.go — fixed
  • api/internal/handlers/openapi.go — searched for "200 MB" / "200MB"; only correct "50 MiB" / "50 MB" references present
  • api/internal/handlers/deploy.go — already says "50 MB" (was the reference standard)
  • api/internal/handlers/stack.go Redeploy (L1340) — already says "multipart/form-data with a 'manifest' field" (no size lie); registry test does not extend to it today (different invalid_form shape, separate path)

🤖 Generated with Claude Code

mastermanas805 and others added 3 commits May 30, 2026 21:43
…200 MB (B7-P1-1)

POST /stacks/new emitted:

    error:   "invalid_form"
    message: "Request must be multipart/form-data (max 200 MB)"

The "max 200 MB" hint was a lie. The real cap is the global Fiber BodyLimit
of 50 MiB (router.go:169); anything > 50 MiB is rejected upstream by Fiber's
ErrorHandler with `payload_too_large` and never reaches this handler. The
in-handler `invalid_form` arm only fires for malformed multipart bodies
AT OR UNDER 50 MiB.

An agent reading the 200 MB message and building a 100 MB stack tarball got
413 instead of the promised 400 — and a stack-vs-deploy contract drift
(deploy.go correctly says "max 50 MB"). One limit, two truths.

The fix updates stack.go's comment + message to match the real cap and adds
a registry-iterating regression test (rule 18, MULTI-PATH-COVERAGE-RULES.md)
that walks every multipart-upload endpoint emitting `invalid_form` and
asserts the message references 50 (MiB|MB) and does NOT contain known wrong
sizes ("200 MB", "100 MB", "1 GB", etc.). Verified to FAIL pre-fix:

    --- FAIL: TestUploadSizeMessage_NoLies (0.08s)
        --- FAIL: TestUploadSizeMessage_NoLies//stacks/new (0.00s)
            "Request must be multipart/form-data (max 200 MB)" should not contain "200 MB"

…and PASS post-fix.

Coverage block:
    Symptom:        invalid_form message advertises wrong upload cap
    Enumeration:    rg -n '200 MB\|200MB\|max 200\|200 MiB' internal/handlers/
    Sites found:    1 (stack.go:474,478)
    Sites touched:  1
    Coverage test:  TestUploadSizeMessage_NoLies (iterates deploy.New + stack.New)
    Live verified:  pending deploy → curl POST /stacks/new with non-multipart body

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit 313ed16 into master May 30, 2026
16 checks passed
@mastermanas805 mastermanas805 deleted the fix/api-stack-200mb-lie-2026-05-30 branch May 30, 2026 16:58
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.

1 participant