Skip to content

fix(llm): classify Azure payload-size and image-count 400s as context overflow - #40167

Open
dotCipher wants to merge 1 commit into
anomalyco:devfrom
dotCipher:fix/azure-payload-overflow-patterns
Open

fix(llm): classify Azure payload-size and image-count 400s as context overflow#40167
dotCipher wants to merge 1 commit into
anomalyco:devfrom
dotCipher:fix/azure-payload-overflow-patterns

Conversation

@dotCipher

@dotCipher dotCipher commented Aug 2, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #39677

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

isContextOverflow() is what decides whether a failed request gets media-strip compaction and a retry. Its pattern list only covers token/context-window phrasing, so two Azure caps that really mean "your payload is too big" fall through as generic non-retryable errors:

Request content length exceeded 32 MB limit.
Exceeded maximum number of images (50) allowed in the request.

Because the full history is resent on every turn, that leaves the session unrecoverable — the next turn fails identically, and /compact fails too since it sends the same oversized payload.

413 is already handled via /request entity too large/i plus the statusCode === 413 check added in #14562. Azure just spells the same condition as a 400 with a prose message, so these two patterns extend that existing handling to Azure's phrasing. Worth noting it says "content length", not "context length", which is why /context[_ ]length[_ ]exceeded/i doesn't already catch it.

Both patterns are added after the exclusions list, so the throttling/rate-limit carve-out from #39623 still takes precedence.

How did you verify your code works?

  • bun test test/provider-error.test.ts in packages/llm — 3 pass. Added a case asserting both messages classify as overflow, covering the bare message, a status-code-prefixed variant, and the OpenRouter shape where the upstream body arrives escaped inside metadata.raw.
  • The existing rate-limit exclusion test still passes. I also checked throttling, 429, quota, 401, content-filter and 500 messages still do not match, so this doesn't widen classification into retryable errors.
  • bun run typecheck and bunx prettier --check on both changed files.
  • Reproduced against a real wedged session first: 48 image read results, ~70 MB of base64, every turn failing on the 32 MB cap with no way to recover in-product.

Screenshots / recordings

N/A — not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

… overflow

Azure OpenAI enforces two per-request caps that are returned as 400s with
prose messages rather than 413s:

  Request content length exceeded 32 MB limit.
  Exceeded maximum number of images (50) allowed in the request.

Neither matched isContextOverflow, so media-strip compaction never ran and
the oversized history was resent on every turn, leaving the session
permanently unrecoverable (/compact fails identically).

The existing 413 handling and /request entity too large/ pattern already
cover this semantic failure for the 413 spelling; these two patterns extend
the same treatment to Azure's 400 phrasing. Note the near-miss against
/context[_ ]length[_ ]exceeded/ - Azure says "content length", not
"context length".

Patterns are placed after the exclusions list so throttling and rate-limit
messages are still correctly excluded.
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

Image-count 400s (Azure: "Exceeded maximum number of images (50)") are not classified as context overflow, so media-strip compaction never triggers

1 participant