You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[gateway] 30-image cap applied only to some session routes: identical request flips 400/200 with only x-opencode-session changed; capped sessions cannot /compact #51073
The OpenCode Go gateway (https://opencode.ai/zen/go/v1) enforces a 30-image-per-request cap on only some routes: enforcement follows the x-opencode-session routing value and the model. Identical requests (same API key, same model, same payload, sent seconds apart) return 400 Too many images in request: N > 30 with one session id and 200 with another. On a capped route every full-history request fails - including /compact - so a session becomes unrecoverable once its history exceeds 30 images (same class as #39677 / #47487).
Environment
Date: 2026-09-23
Client: ZCode 3.14.3 (win32-x64); provider config name opencode, client-side provider id opencode-go-chat-2
Turn execution failed provider=opencode-go-chat-2 model=deepseek-v4.1-flash request=4c9964bb-0208-4ac5-816e-5bef6aa07af6 reason=invalid_request status=400 retryable=false
Upstream request failed: [invalid_request_error] Too many images in request: 31 > 30
Compaction on the same session (request fff7b328-cc3f-4274-8408-6303273862a5) failed identically: Too many images in request: 33 > 30. The user-visible symptom is the generic Provider rejected the model request. banner, which hides the actual count error.
Controlled A/B - single variable: the x-opencode-session header
31/33 tiny distinct PNGs in one user message, same Authorization, requests sent seconds apart:
x-opencode-session
model
images
result
affected session 37900f3c-...
deepseek-v4.1-flash
30
200
affected session
deepseek-v4.1-flash
31
400 31 > 30 (3/3, both stream:false and stream:true)
affected session
deepseek-v4.1-flash
33
400 33 > 30 (matches production verbatim)
affected session
mimo-v2.6-flash
31
200
random uuid
deepseek-v4.1-flash
31 / 33
200
random uuid
deepseek-v4.1-flash
601
400, but from upstream: .messages[0]: Too many images: max 600 images per request, got 601 (headers x-opencode-endpoint-id: orcarouter-dsv4.1flash, x-opencode-upstream-model-id: deepseek/deepseek-v4.1-flash)
Reading: on fresh session routes the gateway imposes no cap - only the upstream DeepSeek 600-image limit is enforced (different message shape, includes the .messages[] path). The affected route enforces a stale per-model 30 (Too many images in request: N > 30, no path). Same key, so not per-key; same payload, so not payload-dependent; identical model passing vs failing depending only on the session header -> inconsistent cap configuration across the routing pool (some backend still carrying deepseek-v4.1-flash = 30).
Impact
Once history exceeds 30 images, every full-history request on the capped route 400s - including /compact, the only recovery path - so the session is permanently bricked. Workaround used: temporarily switch the model/provider, compact there, switch back.
The same request works or fails purely based on the session header, which is extremely hard for users to diagnose.
Apply image-cap configuration uniformly across all routing targets for a given key/plan - or drop the gateway-side cap for deepseek models entirely and rely on the upstream 600-image limit, which is already enforced and clearly reported.
Call POST https://opencode.ai/zen/go/v1/chat/completions with one API key, model=deepseek-v4.1-flash, and 31 distinct tiny data-URL PNG parts in a single user message (max_tokens: 16, stream: false).
With header x-opencode-session: 37900f3c-f467-4b1d-8885-48e67daa0f39 -> HTTP 400 Too many images in request: 31 > 30 (repeatable 3/3; same with stream: true). 30 images -> 200, 33 images -> 400 33 > 30.
Identical request with x-opencode-session: <any other uuid> -> HTTP 200 within seconds.
Random session header + 601 images -> 400 from upstream instead: .messages[0]: Too many images: max 600 images per request, got 601 (no gateway cap on that route).
Real traffic: once a session history contains >30 images, every full-history turn and /compact fail with 31 > 30 / 33 > 30 (requests 4c9964bb-0208-4ac5-816e-5bef6aa07af6, fff7b328-cc3f-4274-8408-6303273862a5) while the client only shows Provider rejected the model request.
Description
Summary
The OpenCode Go gateway (
https://opencode.ai/zen/go/v1) enforces a 30-image-per-request cap on only some routes: enforcement follows thex-opencode-sessionrouting value and the model. Identical requests (same API key, same model, same payload, sent seconds apart) return400 Too many images in request: N > 30with one session id and200with another. On a capped route every full-history request fails - including/compact- so a session becomes unrecoverable once its history exceeds 30 images (same class as #39677 / #47487).Environment
opencode, client-side provider idopencode-go-chat-2https://opencode.ai/zen/go/v1sk-...redacted)deepseek-v4.1-flash,mimo-v2.6-flash37900f3c-f467-4b1d-8885-48e67daa0f39Errors observed in production traffic
Compaction on the same session (request
fff7b328-cc3f-4274-8408-6303273862a5) failed identically:Too many images in request: 33 > 30. The user-visible symptom is the genericProvider rejected the model request.banner, which hides the actual count error.Controlled A/B - single variable: the
x-opencode-sessionheader31/33 tiny distinct PNGs in one user message, same
Authorization, requests sent seconds apart:x-opencode-session37900f3c-...31 > 30(3/3, bothstream:falseandstream:true)33 > 30(matches production verbatim).messages[0]: Too many images: max 600 images per request, got 601(headersx-opencode-endpoint-id: orcarouter-dsv4.1flash,x-opencode-upstream-model-id: deepseek/deepseek-v4.1-flash)Reading: on fresh session routes the gateway imposes no cap - only the upstream DeepSeek 600-image limit is enforced (different message shape, includes the
.messages[]path). The affected route enforces a stale per-model30(Too many images in request: N > 30, no path). Same key, so not per-key; same payload, so not payload-dependent; identical model passing vs failing depending only on the session header -> inconsistent cap configuration across the routing pool (some backend still carryingdeepseek-v4.1-flash = 30).Impact
/compact, the only recovery path - so the session is permanently bricked. Workaround used: temporarily switch the model/provider, compact there, switch back.Ask
Too many images in request: ...as a recoverable/overflow condition so compaction with media-strip can run (ties into fix(session): cap images per request and classify image-count limit as overflow #47493).I can provide full request/response captures (including
x-opencode-log-idvalues from my probes) or run further controlled probes on request.Related: #47965 (per-model image cap on OpenCode Go), #47487, #39677, #47493
Plugins
None - the report concerns the gateway/server side; client is ZCode 3.14.3
OpenCode version
N/A - gateway behavior observed via ZCode 3.14.3 against https://opencode.ai/zen/go/v1
Steps to reproduce
POST https://opencode.ai/zen/go/v1/chat/completionswith one API key,model=deepseek-v4.1-flash, and 31 distinct tiny data-URL PNG parts in a single user message (max_tokens: 16,stream: false).x-opencode-session: 37900f3c-f467-4b1d-8885-48e67daa0f39-> HTTP 400Too many images in request: 31 > 30(repeatable 3/3; same withstream: true). 30 images -> 200, 33 images -> 40033 > 30.x-opencode-session: <any other uuid>-> HTTP 200 within seconds.model=mimo-v2.6-flash+ 31 images -> HTTP 200..messages[0]: Too many images: max 600 images per request, got 601(no gateway cap on that route)./compactfail with31 > 30/33 > 30(requests4c9964bb-0208-4ac5-816e-5bef6aa07af6,fff7b328-cc3f-4274-8408-6303273862a5) while the client only showsProvider rejected the model request.Screenshot and/or share link
No response
Operating System
Windows 11 (build 26200)
Terminal
N/A - desktop GUI client (ZCode)