Skip to content

fix(snowflake): transform tool_choice string to object format - #23268

Merged
RheagalFire merged 17 commits into
BerriAI:litellm_oss_staging_03_10_2026from
stevejaker:fix/snowflake-tool-choice-format
Mar 10, 2026
Merged

fix(snowflake): transform tool_choice string to object format#23268
RheagalFire merged 17 commits into
BerriAI:litellm_oss_staging_03_10_2026from
stevejaker:fix/snowflake-tool-choice-format

Conversation

@stevejaker

@stevejaker stevejaker commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Snowflake's Cortex API documentation is pretty inconsistent, but it requires tool_choice to be an object, not a string. For example, {"type": "auto"} instead of "auto".

Relevant issues

Fixes #23284

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

🐛 Bug Fix

Changes

  • Updated litellm/llms/snowflake/chat/transformation.py to transform string values for tool_choice to object format

Test plan

  • Unit tests updated and passing
  • Tested against real Snowflake Cortex API with tool calls

Ref: https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/reference/cortex-inference#post--api-v2-cortex-inference-complete-req-body-schema

image

Krish Dholakia and others added 17 commits March 9, 2026 19:33
…ment 'self' (BerriAI#23220)

The bug occurred when user data inadvertently contained reserved Python
keywords like 'self', 'params', or '__class__' as keys. When such a dict
was unpacked via **kwargs to LiteLLM_Params() or GenericLiteLLMParams(),
Python raised TypeError because 'self' was passed both implicitly and
as a keyword argument.

The fix:
- Add a Pydantic model_validator(mode='before') to GenericLiteLLMParams
  that filters out reserved keys ('self', 'params', '__class__') before
  validation
- Move the max_retries str-to-int conversion into the same validator
- Remove the custom __init__ methods from both GenericLiteLLMParams and
  LiteLLM_Params, since the validator now handles the preprocessing
- Clean up unused VERTEX_CREDENTIALS_TYPES import

This fix applies to all classes that inherit from GenericLiteLLMParams,
including LiteLLM_Params and updateLiteLLMParams.

Added comprehensive tests in tests/test_litellm/test_litellm_params_reserved_keys.py

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* add new azure gpt models

* add versionless azure/gpt-5.4 models

* Undated azure/gpt-5.4 alias missing supports_service_tier

* indicate service tier support for azure/gpt-5.3-chat

* fix priority tier pricing for new azure/gpt models
…I#23097)

Claude's API returns assistant messages with empty text blocks
({"type": "text", "text": ""}) alongside tool_use blocks during
multi-turn tool-use conversations. These blocks are rejected when
sent back to the API with "text content blocks must be non-empty".

Sanitization already exists for other code paths (/v1/chat/completions
for both Anthropic and Bedrock), but NOT for the /v1/messages native
path. This adds the same treatment by stripping empty text blocks
from messages in async_anthropic_messages_handler before they are
forwarded to the provider.

Fixes BerriAI#22930
* feat(charity_engine): add Charity Engine provider

Charity Engine is a crowdsourced distributed computing platform that
donates processing power to charitable causes. Its inference API
provides OpenAI-compatible chat, completions, and embeddings endpoints.

* test(charity_engine): add provider config and resolution tests

Verify JSONProviderRegistry config, provider list membership,
model routing for charity_engine/<model>, and Router compatibility.

* feat(charity_engine): add Charity Engine to LlmProviders enum

Enables provider_list membership and LlmProviders.CHARITY_ENGINE
resolution required by the provider and test suite.

* fix(charity_engine): remove api_base_env to fix non-deterministic test

The CHARITY_ENGINE_API_BASE env var could override the base_url in CI,
causing test_charity_engine_provider_resolution to fail intermittently.

* fix(charity_engine): remove trailing slash from base_url
…rriAI#23224)

Any param in DEFAULT_CHAT_COMPLETION_PARAM_VALUES that arrives via
completion(**kwargs) is now automatically forwarded to
get_optional_params(), even if it's not a named parameter of
completion().

Previously, get_non_default_completion_params() excluded params in
OPENAI_CHAT_COMPLETION_PARAMS (assuming they'd be forwarded via the
named-param path), while optional_param_args only contained explicitly
named params. Params like 'store' that were in the known-params list
but not named params fell through both paths and were silently dropped.

The fix adds a 7-line loop after building optional_param_args that
forwards any kwargs present in DEFAULT_CHAT_COMPLETION_PARAM_VALUES.
This means new OpenAI params only need to be added to the constants
dict — no boilerplate changes to 3+ function signatures required.

Fixes BerriAI#23087

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…ze-empty-text-blocks-v1-messages

Revert "fix: strip empty text content blocks in /v1/messages endpoint"
…rriAI#23224)

Any param in DEFAULT_CHAT_COMPLETION_PARAM_VALUES that arrives via
completion(**kwargs) is now automatically forwarded to
get_optional_params(), even if it's not a named parameter of
completion().

Previously, get_non_default_completion_params() excluded params in
OPENAI_CHAT_COMPLETION_PARAMS (assuming they'd be forwarded via the
named-param path), while optional_param_args only contained explicitly
named params. Params like 'store' that were in the known-params list
but not named params fell through both paths and were silently dropped.

The fix adds a 7-line loop after building optional_param_args that
forwards any kwargs present in DEFAULT_CHAT_COMPLETION_PARAM_VALUES.
This means new OpenAI params only need to be added to the constants
dict — no boilerplate changes to 3+ function signatures required.

Fixes BerriAI#23087

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…-optional-params-behavior-ed4a

Revert "Get optional params behavior"
Snowflake's Cortex API requires tool_choice to be an object, not a string.
For example, {"type": "auto"} instead of "auto".

Ref: https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/reference/cortex-inference#post--api-v2-cortex-inference-complete-req-body-schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Mar 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
litellm Error Error Mar 10, 2026 3:03pm

Request Review

@stevejaker

Copy link
Copy Markdown
Contributor Author

@greptileai

@greptile-apps

greptile-apps Bot commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug in the Snowflake Cortex integration where tool_choice string values ("auto", "required", "none") were being forwarded to the Snowflake API as raw strings, which the API does not accept. The fix wraps them as {"type": value} objects in _transform_tool_choice. The return type annotation is also correctly narrowed from Union[str, Dict[str, Any]] to Dict[str, Any].

Key changes:

  • _transform_tool_choice in transformation.py now converts string tool choices to their object equivalent (e.g. "auto"{"type": "auto"}) instead of passing them through unchanged.
  • The updated test correctly asserts the new object format for all three string values.
  • All tests remain pure unit tests with no real network calls, which aligns with the repository's test policy.

Implementation details:
The fix handles three input cases:

  1. String values are wrapped as {"type": value}
  2. Dict with type: "function" are converted to Snowflake's {"type": "tool", "name": [function_name]} format
  3. Already-formatted Snowflake objects pass through unchanged

This is a minimal, targeted bug fix with no side effects on unrelated functionality.

Confidence Score: 5/5

  • This PR is safe to merge — it's a targeted, well-tested bug fix with no side effects on unrelated functionality.
  • The change is minimal and isolated to a single transformation method. The logic is straightforward and aligns with Snowflake's documented API requirement. The existing test was updated to match the new behavior, and no network calls are made in tests. No backwards-incompatible breakage is introduced since the previous string passthrough was already causing API errors. The return type annotation is correctly narrowed.
  • No files require special attention.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[tool_choice input] --> B{isinstance str?}
    B -- Yes --> C["Return {type: tool_choice}\ne.g. 'auto' → {type: 'auto'}"]
    B -- No --> D{isinstance dict?}
    D -- No --> E[Return tool_choice as-is]
    D -- Yes --> F{type == 'function'?}
    F -- No --> E
    F -- Yes --> G{function_name present?}
    G -- No --> E
    G -- Yes --> H["Return {type: 'tool', name: [function_name]}"]
Loading

Last reviewed commit: 68617bf

@stevejaker
stevejaker marked this pull request as ready for review March 10, 2026 15:08
@RheagalFire
RheagalFire changed the base branch from main to litellm_oss_staging_03_10_2026 March 10, 2026 19:33
@RheagalFire
RheagalFire merged commit 2341a38 into BerriAI:litellm_oss_staging_03_10_2026 Mar 10, 2026
32 of 38 checks passed
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…I#23268)

* fix(snowflake): transform tool_choice string to object format

Snowflake's Cortex API requires tool_choice to be an object, not a string.
For example, {"type": "auto"} instead of "auto".

Ref: https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/reference/cortex-inference#post--api-v2-cortex-inference-complete-req-body-schema
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.

[Bug]: Snowflake tool_choice string values rejected

6 participants