Repository navigation
chore(release): backport #42388 and #41462 to stable/1.102.x - #42618
Conversation
…t and policy close (#42388) * fix(realtime): surface an upstream handshake refusal as an error event and policy close Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(realtime): tidy the handshake refusal e2e Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(realtime): keep upstream exception text out of the Azure client error Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(realtime): map handshake refusal close codes with a lookup Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> (cherry picked from commit 2bab39e)
…quest_metadata_keys feat(otel): promote nested request metadata keys to litellm.metadata.* span attributes (cherry picked from commit 79fc515)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
|
|
…s imports The two redaction tests raised the deprecated InvalidStatusCode, which the websockets 15 asyncio client never raises, and asserted the raw 403 close code that the handshake refusal path replaced with 1008. The refusal path builds its close reason from the status code alone, so there is no secret to redact there, and the handshake refusal tests already cover the error event and the 1008 close. Those refusal tests only passed when run after a sibling test had imported websockets.asyncio.client, since websockets lazy-loads its exceptions submodule. Importing InvalidStatus, Response, and Headers from their own submodules makes them pass in any order. (cherry picked from commit 54dbe8e)
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 5aa45f1. Configure here.
…02.1) (#736) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.102.0` → `v1.102.1` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.102.1`](https://github.com/BerriAI/litellm/releases/tag/v1.102.1) [Compare Source](BerriAI/litellm@v1.102.0...v1.102.1) ##### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.102.1/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** ##### What's Changed - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42538](BerriAI/litellm#42538) - feat(typesafe): backport the jev change set to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42595](BerriAI/litellm#42595) - chore(release): backport [#​42388](BerriAI/litellm#42388) and [#​41462](BerriAI/litellm#41462) to stable/1.102.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42618](BerriAI/litellm#42618) **Full Changelog**: <BerriAI/litellm@v1.102.0...v1.102.1> </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/London) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDguMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwOC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.hayden.moe/hayden/phoebe/pulls/736
…02.1) (#2200) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.102.0` → `v1.102.1` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/6) for more information. --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.102.1`](https://github.com/BerriAI/litellm/releases/tag/v1.102.1) [Compare Source](BerriAI/litellm@v1.102.0...v1.102.1) #### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.102.1/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** #### What's Changed - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42538](BerriAI/litellm#42538) - feat(typesafe): backport the jev change set to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42595](BerriAI/litellm#42595) - chore(release): backport [#​42388](BerriAI/litellm#42388) and [#​41462](BerriAI/litellm#41462) to stable/1.102.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42618](BerriAI/litellm#42618) **Full Changelog**: <BerriAI/litellm@v1.102.0...v1.102.1> </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Rome) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDQuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwNC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.aresu.eu/GiorgioAresu/home-ops/pulls/2200
…02.1) (#267) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.102.0` → `v1.102.1` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.102.1`](https://github.com/BerriAI/litellm/releases/tag/v1.102.1) [Compare Source](BerriAI/litellm@v1.102.0...v1.102.1) #### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.102.1/cosign.pub \ ghcr.io/berriai/litellm:v1.102.1 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** #### What's Changed - fix(anthropic): backport [#​42152](BerriAI/litellm#42152) and [#​42288](BerriAI/litellm#42288) to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42538](BerriAI/litellm#42538) - feat(typesafe): backport the jev change set to stable/1.102.x for v1.102.1 by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42595](BerriAI/litellm#42595) - chore(release): backport [#​42388](BerriAI/litellm#42388) and [#​41462](BerriAI/litellm#41462) to stable/1.102.x by [@​devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#​42618](BerriAI/litellm#42618) **Full Changelog**: <BerriAI/litellm@v1.102.0...v1.102.1> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwNS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.greyrock.io/todd/home-ops/pulls/267
TLDR
Problem this solves:
requester_metadata.trace_id) to OTEL span attributesHow it solves it:
InvalidStatus, send anerrorevent, close 1008/1013/1011 by upstream HTTP statuslitellm.metadata.<path>on OTEL v1 and v2User Flow
Before: a developer connecting to a realtime deployment whose Azure credential is rejected sees the socket vanish with no explanation, and a platform team cannot join the gateway's LLM span to their own trace
wscat -c "wss://litellm-domain/v1/realtime?model=azure-realtime" -H "Authorization: Bearer sk-..."Connected (press CTRL+C to quit)Disconnected (code: 1006, reason: "")callback_settings.otel.baggage_metadata_keys: [requester_metadata.trace_id]and the developer sends POST https://litellm-domain/v1/chat/completions with"metadata": {"trace_id": "abc"}litellm.metadata.trace_idattributeAfter: the realtime client is told what the upstream said and the caller's trace id lands on the span
wscat -c "wss://litellm-domain/v1/realtime?model=azure-realtime" -H "Authorization: Bearer sk-..."Connected (press CTRL+C to quit){"type": "error", "error": {"type": "server_error", "message": "Upstream realtime handshake rejected with HTTP 401"}}, then wscat printsDisconnected (code: 1008, reason: "Upstream realtime handshake rejected with HTTP 401")baggage_metadata_keysand the developer sends the same POST https://litellm-domain/v1/chat/completions with"metadata": {"trace_id": "abc"}litellm.metadata.trace_id=abc; non-allowlisted metadata stays off the spanRelevant issues
Backport of #42388 (customer report via Pylon #8933) and #41462 (customer request via Pylon #8571) to stable/1.102.x, plus the test-only follow-up #42624. All three are merged on main and reachable from origin/main. #42152 and #42288 from the original backport list are already on the line via #42538. The Jev passthrough backport stays on #42595
Affected release
Backport target stable/1.102.x, tip version 1.102.1 (not yet tagged or published, so no version bump in this PR)
Linear ticket
Resolves LIT-7058, LIT-7760
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
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@greptileaito re-request a review after pushing changes)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: two proxies with the same config, real Azure and OpenAI keys, OTel v2 on (
LITELLM_OTEL_V2=true) withcallback_settings.otel.baggage_metadata_keys: [requester_metadata.trace_id, requester_metadata.nested.deep]and a console span exporter writing to the proxy log.azure-realtime-badkeyis a real Azure realtime deployment with a wrong key. Before runs the merge base on port 4100, After runs this PR's tip on port 4200. The chat payload is{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Reply with exactly: pong"}],"max_tokens":5,"metadata":{"trace_id":"abc","nested":{"deep":"x"}}}. Screen recording of this exact run is in the Slack proof thread: https://berriaillm.slack.com/archives/D0BE48UMS58/p1790114060712649?thread_ts=1790114060.712649&cid=D0BE48UMS58Before (89000e4)
Realtime handshake refused upstream
wscat -c "ws://127.0.0.1:4100/v1/realtime?model=azure-realtime-badkey" -H "Authorization: Bearer sk-bp1102"Connected (press CTRL+C to quit)thenDisconnected (code: 1006, reason: ""), no event receivedNested metadata promoted to OTEL span attributes
curl -s http://127.0.0.1:4100/v1/chat/completions -H "Authorization: Bearer sk-bp1102" -H "Content-Type: application/json" -d '<payload above>'assistant: ponggrep -cE "litellm.metadata.(trace_id|nested)" proxy-before.logprints0After (5aa45f1)
Realtime handshake refused upstream
wscat -c "ws://127.0.0.1:4200/v1/realtime?model=azure-realtime-badkey" -H "Authorization: Bearer sk-bp1102"Connected (press CTRL+C to quit)< {"type": "error", "error": {"type": "server_error", "message": "Upstream realtime handshake rejected with HTTP 401"}}Disconnected (code: 1008, reason: "Upstream realtime handshake rejected with HTTP 401")Nested metadata promoted to OTEL span attributes
curl -s http://127.0.0.1:4200/v1/chat/completions -H "Authorization: Bearer sk-bp1102" -H "Content-Type: application/json" -d '<payload above>'assistant: ponggrep -oE "\"litellm.metadata.(trace_id|nested)[^,]*" proxy-after.log | tail -3prints"litellm.metadata.nested.deep": "x","litellm.metadata.trace_id": "abc","litellm.metadata.nested.deep": "x"(24 matches)Proxy sanity on the tip:
/health/liveliness200,/v1/models200 listing the three deployments, a plain chat completion answersOk!. OpenAI realtime with a bad key behaves the same before and after because OpenAI accepts the upgrade and returns its own error event over the socket, so only the Azure leg exercises the handshake pathType
🐛 Bug Fix
🆕 New Feature
🚄 Infrastructure
Caveats (if any)
Low
-m 1), so its commit subject readsMerge pull request #41462; the body carries the feat title and the cherry-pick footerllm_http_handler.py(awaitvsreturn awaiton the line before the changed hunk); changed lines identical, patch-id differs for that reason aloneInvalidStatusCodetoInvalidStatus, which on the line's pinned websockets 15.0.1 is not a superclass ofInvalidStatusCode. Two tests on the line raised the deprecated class and asserted a 403 close code; test(realtime): drop legacy InvalidStatusCode tests and pin websockets imports #42624 removes them on main and is picked here so the branch tracks main exactly2.9in uv.lock (upstream tag name), equal to 2.9.0, and only ships in the ci group, so it does not appear in the default runtime venvBackport qualification
Base 89000e4 (origin/stable/1.102.x tip). All picks applied with zero conflicts,
.githubuntouched, every referenced identifier resolves on the line. Targeted tests: 910 passed at base, 924 passed after the picks with zero new failures; every unit test from both source PRs passes; the three test files touched by #42624 pass alone and together (25/25). ruff check clean on touched files, mypy error count unchanged versus base (76 both sides), ruff format debt unchanged versus base. Lock diff is confined to the anyio and soupsieve entriesFull
tests/test_litellmrun on both trees (four sequential chunks each, same test list, whole-suite runs OOM on this box): base 71 failed + 1 error / 55598 passed, branch before #42624 76 failed + 1 error / 55636 passed. The 13 new-on-branch ids were rerun alone: 9 pass alone (flaky settings and batch tests), 2 fail alone on base too (external mode lookup and tokenizer env), 2 were the stale redaction tests now removed by the #42624 pick. No unresolved regression remains at the tipScanner: baseline Critical and Medium anyio findings and both soupsieve Mediums are gone after the bump; no new findings versus base
Gauntlet (universal, standard depth, five lenses, clean tree pinned at 5aa45f1) returned SURVIVED on all five sub-claims: identifier and config-key closure, both picks delivering their behavior on this line, no broken stable-only callers, anyio 4.14.2 and soupsieve 2.9 resolving as expected, and the three #42624 test files passing alone and together with no remaining
InvalidStatusCodetest. An earlier run at da246e9 refuted only a mis-worded dependency clause (it required soupsieve in the runtime venv, where the ci group never installs it) and was classed not a regressionFinal Attestation
Note
Medium Risk
Touches realtime WebSocket error handling and OTEL attribute/baggage promotion across proxy and integrations; behavior changes are intentional but affect observability and client-visible close semantics.
Overview
Backports two customer-facing fixes to stable/1.102.x: clearer realtime failures when the upstream WebSocket handshake is rejected, and allowlisted promotion of nested caller metadata onto OpenTelemetry spans.
Realtime: Upstream handshake failures now catch
InvalidStatus(replacing deprecatedInvalidStatusCode) and use sharedclose_after_upstream_handshake_refusal: emit an OpenAI-styleerrorevent, then close with RFC-appropriate codes (e.g. 401/403 → 1008, 429 → 1013). Applied across proxy, OpenAI/Azure handlers, and generic HTTP realtime paths; Azure also sends an error event on unexpected internal failures.OTEL: Adds
baggage_metadata_keys/LITELLM_OTEL_BAGGAGE_METADATA_KEYSon v1 and v2. Nestedrequester_metadatais flattened and allowlisted paths (e.g.requester_metadata.trace_id) stamplitellm.metadata.trace_idon spans and request baggage from the pre-call hook, without dumping unlisted keys.Tests and e2e cover both behaviors; lockfile bumps anyio and soupsieve only.
Reviewed by Cursor Bugbot for commit 5aa45f1. Bugbot is set up for automated code reviews on this repo. Configure here.
Link to Devin session: https://app.devin.ai/sessions/97da7793a06d4de3b4561b4a605cb3a9
Open in Devin Desktop: https://app.devin.ai/desktop/session/97da7793a06d4de3b4561b4a605cb3a9?variant=devin