fix: Altimate Base 413 HTML body and missing header timeout
Issue for this PR
Closes #1255
Type of change
- Bug fix
- New feature
- Refactor / code improvement
- Documentation
What does this PR do?
Fixes two client-side Altimate Base bugs found by live-prod E2E of the v0.11.0-beta.2 release.
Bug 1 — 413 oversize error showed a generic message instead of the friendly one.
FreeTier.describeRequestTooLarge in packages/opencode/src/altimate/free/client.ts did JSON.parse(body) in a try/catch that returned undefined on a parse failure. In production, oversized requests are rejected by the gateway's edge proxy with a raw HTML error page (not a JSON body), so the parse always throws for that case, the function always returned undefined, and the user saw a generic fallback error instead of the friendly "your request is too large — start a new session or shorten it" message.
Fix: describeRequestTooLarge now takes { status, body } instead of a bare body string. Its logic is now:
- If the body parses as JSON and matches the known
request_too_largeshape, keep the existing specific message (with the KB byte-count detail when present). - If the body parses as JSON but is a different shape (e.g. another provider's 413, or an unrelated gateway error), still return
undefined— unchanged behavior, no false positives even though the status is 413. - If the body does not parse as JSON (or is empty) and the status is
413, return the same friendly fallback message the JSON path produces. - Any non-413 status still returns
undefinedfor an unparseable body — unchanged.
The sole caller in packages/opencode/src/provider/error.ts already knew the status was 413 before calling (it gates on input.error.statusCode === 413); it now threads input.error.statusCode through explicitly so the function itself can make the same decision without relying on caller-side control flow alone. All existing test call sites were updated to the new object signature.
Bug 2 — Altimate Base provider had no client-side header timeout.
The "altimate-free" loader in packages/opencode/src/provider/provider.ts returned options: { baseURL, apiKey, fetch } with no headerTimeout, unlike the openai loader in the same file, which sets headerTimeout: OPENAI_HEADER_TIMEOUT_DEFAULT. If the gateway hung before sending response headers, a request through Altimate Base had no client-side timeout and could hang the CLI indefinitely.
Fix: added headerTimeout: OPENAI_HEADER_TIMEOUT_DEFAULT to the altimate-free loader's options, matching the openai loader's existing default.
How did you verify your code works?
bun run typecheck(root, via turbo) — passes across all 15 packages.- Added/extended unit tests:
- New cases in
test/altimate/altimate-base-rate-limit-messages.test.ts: a raw-HTML 413 body returns the friendly fallback; an empty/absent-body 413 returns the same fallback; a 413 with the known JSON shape still returns the specific byte-count message (not the fallback); a non-413 status with an HTML body still returnsundefined; a 413 with valid-but-unrelated JSON still returnsundefined. - New integration test in
test/provider/error.test.tsexercising the fullProviderError.parseAPICallErrorpath with a 413 + raw HTML body, asserting the friendly message comes out end-to-end. - Extended the existing Altimate Base provider-shape test in
test/provider/provider.test.tsto assertoptions.headerTimeoutis set to the same default theopenailoader uses. - Updated every existing
describeRequestTooLargecall site (production and test) to the new{ status, body }signature.
- New cases in
- Ran the full affected suites locally:
test/altimate/altimate-base-rate-limit-messages.test.ts,test/altimate/altimate-base-error-surfacing.test.ts,test/provider/error.test.ts,test/provider/provider.test.ts,test/provider/header-timeout.test.ts, and the fulltest/altimate/directory — all green (5104 pass / 0 fail across the altimate suite; 150 pass / 0 fail for the four directly-targeted files). - Ran
bun run script/upstream/analyze.ts --markers --base origin/main --strict— reports no upstream-shared files were touched (client.tsandprovider.tsare altimate-owned, not upstream-shared), so no marker violations; new hunks are still wrapped inaltimate_changecomments for consistency with the surrounding code.
Not verified: the 413 fix is verified by unit test (a synthetic raw-HTML body) and by the parseAPICallError integration test, but has not been re-run against a live oversized request through the real production nginx edge — that would require reproducing a >1MiB request against the live gateway, which wasn't done as part of this fix.
Screenshots / recordings
N/A — no UI change.
Checklist
- I have tested my changes locally
- I have not included unrelated changes in this PR
[!NOTE]
Low Risk
Localized Altimate Base error mapping and provider timeout defaults; behavior is well covered by unit/integration tests with no auth or data-model changes.
Overview
Fixes two Altimate Base client bugs: oversized-request errors and hung gateway calls.
413 / request too large: describeRequestTooLarge now takes { status, body } instead of a raw body string. When the response is 413 with HTML or empty/unparseable bodies (production nginx edge rejection), it returns the same friendly Altimate Base message instead of undefined, so parseAPICallError no longer falls through to generic context_overflow. JSON request_too_large responses still get byte-count detail when available; unrelated 413 JSON shapes are left unchanged.
Header timeout: The altimate-free provider loader sets headerTimeout: OPENAI_HEADER_TIMEOUT_DEFAULT (10s), matching OpenAI so a stalled gateway cannot hang the CLI indefinitely.
Tests cover nginx HTML 413 end-to-end, edge cases for the new signature, and provider headerTimeout assertion.
Reviewed by Cursor Bugbot for commit eeccaa98269bd9c959fd060cf97d55ba60d08bc5. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Fixes two Altimate Base client-side bugs found in live-prod E2E: oversized requests now show the friendly "request too large" message even when the gateway rejects with raw HTML, and a hung gateway response no longer hangs the CLI. Closes #1255.
Bug Fixes
describeRequestTooLargenow takes{ status, body }and returns the friendly message on any 413, even when the body doesn't parse as JSON.- A 413 with valid JSON that isn't the known
request_too_largeshape still returnsundefined, as does any non-413 status. - The
altimate-freeprovider loader now setsheaderTimeout, matching theopenailoader's default.
Summary by CodeRabbit
-
Bug Fixes
- Improved handling of oversized request errors, including gateway responses with empty or unparseable bodies.
- Displays a friendly “request too large” message for HTTP 413 responses instead of a generic error.
- Prevents stalled gateway responses by applying a 10-second response-header timeout.
-
Tests
- Added coverage for malformed, empty, and oversized response scenarios.