Skip to content

fix: repair seven regressions caught by CircleCI on main - #42640

Merged
yuneng-berri merged 6 commits into
mainfrom
litellm_ci_regression_fixes_0922
Sep 23, 2026
Merged

yuneng-berri merged 6 commits into
mainfrom
litellm_ci_regression_fixes_0922

Conversation

@yuneng-berri

@yuneng-berri yuneng-berri commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • CircleCI on main has seven reds that are real regressions, not stale tests
  • Fine-tuned Vertex endpoints and Gemma get Gemini 3 defaults injected
  • Azure DALL-E 3 image calls come back with no cost
  • Bedrock invoke Kimi streams yield zero chunks
  • Pre-routing rejects land in spend logs with an empty model group
  • Bedrock regional rows lost capability flags their base rows have
  • New regional Bedrock rows fail the converse whitelist check

How it solves it:

  • Gemini 3 detection skips numeric and gemini/<id> fine-tunes and gemma-
  • Image cost lookup also tries the azure/<quality>/<size>/dall-e-3 key
  • bedrock/invoke/moonshot streams go through an OpenAI-shaped chunk decoder
  • Pre-routing rejects keep the public model group in logging metadata
  • Base rows' supports_* flags are mirrored onto regional and cross-region copies
  • Whitelist gets the new nemotron and us-gov Opus 5.5 rows

User Flow

Before: an admin whose users call Azure DALL-E 3 through the proxy sees those calls priced at nothing, and blocked requests show up on the Usage page with no model

  1. A developer sends POST http://localhost:4000/v1/images/generations with "model": "dall-e-3", "quality": "hd", "size": "1024x1024"
  2. The image comes back 200, but the response has no x-litellm-response-cost header and spend stays at $0
  3. A request to internal-model is blocked by a guardrail with a 400
  4. GET http://localhost:4000/spend/logs?request_id= shows that row with model_group: "", so the Usage page can't group it under internal-model

After: the same image call is priced and the blocked request is grouped under its public model name

  1. A developer sends the same POST http://localhost:4000/v1/images/generations
  2. The image comes back 200 with x-litellm-response-cost: 0.07999586304
  3. A request to internal-model is blocked by a guardrail with a 400
  4. GET http://localhost:4000/spend/logs?request_id= shows that row with model_group: "internal-model"

Relevant issues

Affected release

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Scope note: this bundles seven separate regressions on purpose, one per CircleCI red on main, so main goes green in one merge. Each one has its own mutation-checked test

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Shared setup: a proxy started with the config below, master key sk-proof-1234. The Azure key in our env is currently rejected by Azure, so dall-e-3 points at a local stand-in that returns an Azure-shaped image response. The price is computed by the proxy from that response, same as with real Azure. internal-model is blocked by a guardrail before it's routed, so no upstream call is made either way

model_list:
  - model_name: dall-e-3
    litellm_params: {model: azure/dall-e-3, api_base: http://127.0.0.1:18099, api_key: mock-key, api_version: "2024-02-01"}
  - model_name: internal-model
    litellm_params: {model: openai/gpt-4.1, api_base: http://127.0.0.1:18099/v1, api_key: mock-key}
guardrails:
  - guardrail_name: proof-reject
    litellm_params: {guardrail: reject_guard.RejectGuard, mode: pre_call, default_on: false}
general_settings: {master_key: sk-proof-1234}

Before (a80379b)

Azure DALL-E 3 cost

  1. curl -s -D - -o /dev/null localhost:4001/v1/images/generations -H "Authorization: Bearer sk-proof-1234" -H 'content-type: application/json' -d '{"model":"dall-e-3","prompt":"a cat","size":"1024x1024","quality":"hd"}' | grep -iE '^HTTP|response-cost'
  2. Output: HTTP/1.1 200 OK and no x-litellm-response-cost header

Blocked request model group

  1. curl -s localhost:4001/v1/chat/completions -H "Authorization: Bearer sk-proof-1234" -H 'content-type: application/json' -d '{"model":"internal-model","messages":[{"role":"user","content":"hi"}],"guardrails":["proof-reject"]}' returns 400 blocked by proof guardrail, call id 22f9cb43-a67f-4f91-a5ea-270bd19c3c61
  2. curl -s "localhost:4001/spend/logs?request_id=22f9cb43-a67f-4f91-a5ea-270bd19c3c61" -H "Authorization: Bearer sk-proof-1234" gives (model, model_group, status) = ('openai/gpt-4.1', '', 'failure')

After (5073d44)

Azure DALL-E 3 cost

  1. Same curl
  2. Output: HTTP/1.1 200 OK and x-litellm-response-cost: 0.07999586304

Blocked request model group

  1. Same curl returns 400 blocked by proof guardrail, call id 61d69fdd-a140-46c2-b2de-98907a8e4a64
  2. Same spend log lookup gives ('openai/gpt-4.1', 'internal-model', 'failure')

The tip after 5073d44 only adds a merge of main, which touches none of the files on these two paths

Type

🐛 Bug Fix

Caveats (if any)

Medium

  • No live proof for Kimi streaming: the AWS creds in our env are expired
    • Covered by sync and async tests that replay real Bedrock event-stream frames
  • No live proof for fine-tuned Vertex endpoints: no Vertex creds here
    • A live gemini/gemma-4-31b-it call succeeds before and after; the only difference is the injected temperature: 1.0
  • The Gemini 3 detection assumes any gemini/<id> not starting with gemini- is a fine-tune
    • An unprefixed alias like gemini/learnlm would now read as pre-Gemini-3, which only affects its default temperature

Low

  • Blocked requests to multi-deployment groups still log an empty model group
    • Their model field is already the public name, so Usage groups them correctly, same as before
  • Azure dall-e-2 now prices at $0 instead of raising, because its Azure row is priced at 0.0
  • Kimi streams don't strip <reasoning> tags from content yet
  • The Bedrock invoke gpt-oss (openai) provider may have the same decoder gap; not touched here
  • jp.anthropic.claude-opus-4-7 lacks supports_output_config, which was already missing before this PR; left alone
  • test_utils.py::test_wrapper_async_does_not_fire_failure_hook_for_post_success_error fails on main itself; not touched here

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

- vertex_ai: stop treating fine-tuned endpoint ids (numeric or
  vertex_ai/gemini/<id>) and gemma models as Gemini 3+, which injected
  temperature=1.0 and Gemini 3 thinking config into their requests (#42465)
- cost: price Azure DALL-E 3 from its azure/<quality>/<size>/dall-e-3 rows;
  it only worked through the OpenAI rows that #42435 removed
- bedrock: stream bedrock/invoke/moonshot through an OpenAI-shaped chunk
  decoder; the generic decoder dropped every chunk, which the
  supports_response_schema flag from #42338 un-skipped in CI
- proxy: keep the public model_group on pre-routing rejections so the Usage
  page groups them under the model name, not the deployment (#41077)
- cost map: mirror the base rows' capability flags onto Bedrock regional and
  cross-region copies (#42254 and later syncs)
- whitelist the new regional Bedrock rows from #42543 and #42588 for the
  converse routing check, following the existing regional-row convention
…_fixes_0922

# Conflicts:
#	tests/local_testing/test_completion_cost.py
@greptile-apps

greptile-apps Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

Complete model-group attribution for multi-deployment rejections and satisfy the repository typing requirements before merging

Findings

  1. P1 Multi-deployment groups remain unlogged ▶
  2. P2 Required type annotations missing ▶

Summary

This PR repairs image-cost lookup, Bedrock invoke streaming, Gemini model classification, failure-log attribution, and Bedrock model metadata

  • Adds provider-first image pricing keys and an OpenAI-compatible decoder for Moonshot invoke streams
  • Excludes fine-tuned Vertex identifiers and Gemma from Gemini 3 defaults
  • Synchronizes regional capability flags and extends Bedrock whitelists
  • Failure-log attribution remains incomplete for model groups with multiple deployments
  • New annotations need to satisfy the repository’s typing requirements

Reviews (1) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..."

Comment thread litellm/proxy/utils.py
Comment thread litellm/llms/bedrock/chat/invoke_handler.py Outdated
@codspeed

codspeed Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_ci_regression_fixes_0922 (ba7179a) with main (30004f5)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (bc911ab) during the generation of this report, so 30004f5 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@codecov

codecov Bot commented Sep 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri mateo-berri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thx!

@yuneng-berri
yuneng-berri merged commit b395bfe into main Sep 23, 2026
125 of 138 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_ci_regression_fixes_0922 branch September 23, 2026 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants