Skip to content

Root cause fix - migrate all logging update to use 1 function - for centralized kwarg updates - #23659

Merged
4 commits merged into
mainfrom
litellm_dev_03_14_2026_p2
Mar 16, 2026
Merged

Root cause fix - migrate all logging update to use 1 function - for centralized kwarg updates#23659
4 commits merged into
mainfrom
litellm_dev_03_14_2026_p2

Conversation

@ghost

@ghost ghost commented Mar 14, 2026

Copy link
Copy Markdown

Relevant issues

Root cause fix for #23185

Pre-Submission checklist

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

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Type

🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test

Changes

@vercel

vercel Bot commented Mar 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Mar 14, 2026 8:24pm

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bac05524a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread litellm/responses/main.py
Comment on lines +742 to +743
litellm_logging_obj.update_from_kwargs(
kwargs=kwargs,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include explicit metadata when logging responses calls

responses() takes metadata as an explicit parameter, but this pre-call logging now passes only kwargs into update_from_kwargs; since explicit params are not inside kwargs, request metadata is dropped from litellm_params for this path. Any callback/cost logic that depends on model_call_details["litellm_params"]["metadata"] (the behavior preserved before this change) will silently lose metadata when users call litellm.responses(..., metadata=...).

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Mar 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a centralized update_from_kwargs helper on the Logging class that automatically extracts metadata and litellm_metadata from the raw kwargs dict, then delegates to the existing update_environment_variables. All 22 call sites across the SDK's non-chat endpoints (batches, containers, evals, images, responses, videos, vector stores, etc.) are migrated to the new helper, eliminating the per-call boilerplate of manually plumbing "metadata": kwargs.get("metadata", {}) into litellm_params. This is the root-cause fix for #23185, where routes like /messages that stored pricing info under kwargs["litellm_metadata"] were not having that data forwarded to use_custom_pricing_for_model.

Key observations:

  • Core logic is soundupdate_from_kwargs first collects metadata/litellm_metadata from kwargs, then merges explicitly-passed litellm_params on top (so callers can always override), and finally calls the unchanged update_environment_variables. The merge order is tested thoroughly.
  • Test suite is comprehensive at the unit levelTestUpdateFromKwargs in test_litellm_logging.py covers extraction, backfill, priority, custom-pricing detection, and empty-kwargs scenarios.
  • The regression test for [Bug]: Custom Pricing is broken for /messages and /responses endpoints (streaming) #23185 has been weakenedtest_async_anthropic_messages_handler_passes_litellm_metadata in test_llm_http_handler.py now mocks out update_from_kwargs entirely and only asserts that litellm_metadata is present in the forwarded kwargs dict. It no longer verifies that the metadata ends up in litellm_params (where use_custom_pricing_for_model reads it). The dedicated unit tests compensate partially but the integration guard is weaker.
  • builtins.list fix in vector_stores/main.py — a subtle but correct fix for a local function named list shadowing the Python builtin in an isinstance check.
  • Pre-submission checklist is entirely unchecked — no CI links or test evidence is provided in the PR description.

Confidence Score: 4/5

Important Files Changed

Filename Overview
litellm/litellm_core_utils/litellm_logging.py Adds new update_from_kwargs convenience method that automatically extracts metadata/litellm_metadata from the raw kwargs dict, centralising the metadata forwarding logic that was previously scattered across all callers.
tests/test_litellm/llms/custom_httpx/test_llm_http_handler.py The regression test for issue #23185 was updated to mock update_from_kwargs instead of update_environment_variables, but the new assertion only checks that litellm_metadata is in the kwargs dict — not that it is correctly extracted into litellm_params, weakening the original regression guard.
tests/test_litellm/litellm_core_utils/test_litellm_logging.py Adds comprehensive TestUpdateFromKwargs test class covering metadata extraction, backfill logic, priority order, custom-pricing detection, and empty-kwargs edge cases — good unit coverage of the new method.
litellm/llms/custom_httpx/llm_http_handler.py Migrates the Anthropic messages handler to update_from_kwargs, removing the manual metadata/litellm_metadata extraction from litellm_params — the direct call site for issue #23185.
litellm/responses/main.py Migrates all six response API entry points (responses, delete_responses, get_responses, list_input_items, cancel_responses, compact_responses) to update_from_kwargs, correctly using local_vars (which already includes kwargs) as the source dictionary.
litellm/videos/main.py Migrates video API logging to update_from_kwargs; also adds seconds, extra_headers, extra_query, extra_body to overloads and removes api_key/api_base/api_version from typed overloads (these remain accessible via **kwargs).
litellm/batches/main.py Migrates create_batch and retrieve_batch to update_from_kwargs; removes the explicit "metadata": metadata key from the litellm_params dict, delegating extraction to the new helper.
litellm/vector_stores/main.py Migrates all vector store operations; also adds import builtins to safely use builtins.list in the mock-response isinstance check where the local list function shadowed the builtin.
tests/test_litellm/images/test_image_edit_utils.py Updates capturing mock to intercept update_from_kwargs; manually mirrors the metadata-extraction logic inside the capturing stub so the downstream assertion on captured_litellm_params remains valid.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Call site\n(batches, responses, images, videos, etc.)"] -->|"update_from_kwargs(kwargs=kwargs, litellm_params=..., ...)"| B["update_from_kwargs"]

    B --> C{"'metadata'\nin kwargs?"}
    C -->|Yes| D["base['metadata'] = kwargs['metadata']"]
    C -->|No| E{"'litellm_metadata'\nin kwargs?"}
    D --> E

    E -->|"Yes (and is dict)"| F["base['litellm_metadata'] = kwargs['litellm_metadata']"]
    F --> G{"'metadata' already\nset in base?"}
    G -->|No| H["base['metadata'] = litellm_metadata.copy()"]
    G -->|Yes| I["skip backfill"]
    E -->|No| J["no-op"]

    H --> K["Merge caller litellm_params\nover base (caller wins)"]
    I --> K
    J --> K

    K --> L["update_environment_variables(\n  litellm_params=merged,\n  optional_params=...,\n  model=..., user=...\n)"]

    L --> M["self.litellm_params updated\n(metadata + litellm_metadata\nnow present)"]
    M --> N["use_custom_pricing_for_model\nchecks litellm_params\n→ detects custom pricing ✓"]
Loading

Comments Outside Diff (1)

  1. tests/test_litellm/llms/custom_httpx/test_llm_http_handler.py, line 186-233 (link)

    Regression test weakened for issue [Bug]: Custom Pricing is broken for /messages and /responses endpoints (streaming) #23185

    The original regression test for [Bug]: Custom Pricing is broken for /messages and /responses endpoints (streaming) #23185 verified the complete end-to-end data flow: that litellm_metadata ended up inside litellm_params as seen by use_custom_pricing_for_model. The new test only verifies the first hop — that litellm_metadata is present in the kwargs dict forwarded to update_from_kwargs. Since update_from_kwargs is fully mocked (Mock()), the test no longer validates that the metadata is correctly extracted and placed into litellm_params at all.

    If a future regression broke the extraction logic inside update_from_kwargs, this test would still pass. The unit tests in TestUpdateFromKwargs partially compensate, but the integration regression from [Bug]: Custom Pricing is broken for /messages and /responses endpoints (streaming) #23185 is no longer guarded here.

    Consider removing the mock for update_from_kwargs and instead asserting on logging_obj.litellm_params after the call, similar to how TestUpdateFromKwargs.test_custom_pricing_detected_via_litellm_metadata works:

    # Instead of:
    mock_logging_obj.update_from_kwargs = Mock()
    # ...
    mock_logging_obj.update_from_kwargs.assert_called_once()
    kwargs_arg = ...
    assert "litellm_metadata" in kwargs_arg
    
    # Prefer a real logging obj + assert the downstream effect:
    assert "litellm_metadata" in mock_logging_obj.litellm_params
    assert mock_logging_obj.litellm_params["litellm_metadata"]["model_info"] == custom_model_info

    Rule Used: # Code Review Rule: Mock Test Integrity

    What:... (source)

Last reviewed commit: 90252ee

@ghost
ghost merged commit ca4329a into main Mar 16, 2026
91 of 97 checks passed
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…entralized kwarg updates (BerriAI#23659)

* fix: Fixes BerriAI#23185

* fix(responses/main.py): ensure litellm metadata custom cost works

* refactor: move all logging updates to a common function, to have just 1 place to update logging kwarg updates
This pull request was closed.
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.

0 participants