Skip to content

fix(gemini): filter params from embedding requests - #24370

Merged
Chesars merged 1 commit into
BerriAI:litellm_staging_03_22_2026from
Chesars:fix/gemini-embedding-drop-unsupported-params
Mar 22, 2026
Merged

fix(gemini): filter params from embedding requests#24370
Chesars merged 1 commit into
BerriAI:litellm_staging_03_22_2026from
Chesars:fix/gemini-embedding-drop-unsupported-params

Conversation

@Chesars

@Chesars Chesars commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #24293

Pre-Submission checklist

  • 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

Type

🐛 Bug Fix

Changes

The Gemini batch embedding transformation spreads all optional_params into the request body via **gemini_params. Params like max_tokens (injected by add_provider_specific_params_to_optional_params for non-OpenAI providers) reach the Gemini API and cause a 400 BadRequestError.

drop_params: true doesn't prevent this because the param is re-injected after the drop_params check runs.

Extract _filter_embed_params() that maps dimensions/task_type and keeps only the fields Gemini embeddings accept (outputDimensionality, taskType, title). Applied to both transform_openai_input_gemini_content and transform_openai_input_gemini_embed_content.

Tests added

  • test_filter_embed_params_drops_unsupported — verifies max_tokens/temperature are filtered
  • test_filter_embed_params_keeps_supported — verifies dimensions/task_type/title pass through
  • test_batch_embed_content_drops_max_tokens — integration test for batchEmbedContents path
  • test_embed_content_drops_max_tokens — integration test for embedContent path

The Gemini batch embedding transformation was spreading all
optional_params into the request body via **gemini_params. Params
like max_tokens (injected by add_provider_specific_params_to_optional_params)
would reach the Gemini API and cause a 400 BadRequestError.

Extract _filter_embed_params() that maps dimensions/task_type and
keeps only the fields Gemini embeddings actually accept
(outputDimensionality, taskType, title). Applied to both
transform_openai_input_gemini_content and
transform_openai_input_gemini_embed_content.

This also fixes drop_params: true not preventing the error, since
the param was re-injected after the drop_params check.

Fixes BerriAI#24293
@vercel

vercel Bot commented Mar 22, 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 22, 2026 8:43pm

Request Review

@greptile-apps

greptile-apps Bot commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a 400 BadRequestError on Gemini embedding requests by introducing a _filter_embed_params() helper that whitelists only the three fields Gemini embeddings accept (outputDimensionality, taskType, title) and applies it to both the batchEmbedContents and embedContent transformation paths.

  • Root cause addressed: add_provider_specific_params_to_optional_params injects max_tokens (and potentially other non-embedding params) into optional_params after the drop_params check runs; previously, these were blindly spread into every Gemini embedding request body via **gemini_params.
  • Fix: _filter_embed_params() centralises param mapping (dimensionsoutputDimensionality, task_typetaskType) and strict whitelist filtering in one place, replacing duplicated inline logic in both transformation functions.
  • Tests: Four new pure unit tests are added — two for the helper function directly and two integration tests through the transformation functions — none of which make real network calls, satisfying the mock-only test policy for this directory.
  • Type safety: The whitelist ({"outputDimensionality", "taskType", "title"}) correctly matches the optional fields declared in the VertexAITextEmbeddingsRequestBody TypedDict that EmbedContentRequest inherits from.

Confidence Score: 5/5

  • This PR is safe to merge — it fixes a targeted 400 error with no backwards-incompatible surface changes.
  • The change is minimal and surgical: it extracts existing inline mapping logic into a shared helper and adds a whitelist filter. The whitelist exactly matches the optional fields of the EmbedContentRequest / VertexAITextEmbeddingsRequestBody TypedDict, so no valid params are dropped. All four new tests are pure unit/mock tests, coverage for both endpoints is present, and no existing tests are weakened.
  • No files require special attention.

Important Files Changed

Filename Overview
litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_transformation.py Extracts a _filter_embed_params() helper that maps OpenAI field names (dimensionsoutputDimensionality, task_typetaskType) and whitelists only the three fields Gemini embeddings actually accept, preventing unsupported params like max_tokens from being spread into the request body.
tests/litellm/llms/vertex_ai/test_gemini_batch_embeddings.py Adds four focused unit tests for the new _filter_embed_params helper and integration tests for both embedding endpoints; all tests are pure mock/unit tests with no real network calls.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["litellm.embedding() called\nwith optional_params\ne.g. {max_tokens: 256, dimensions: 768}"] --> B["_filter_embed_params(optional_params)"]
    B --> C{"Map OpenAI keys"}
    C -->|"dimensions → outputDimensionality"| D["Rename key"]
    C -->|"task_type → taskType"| E["Rename key"]
    C -->|other keys unchanged| F["Keep as-is"]
    D & E & F --> G["Whitelist filter\n_SUPPORTED_EMBED_PARAMS\n= {outputDimensionality, taskType, title}"]
    G -->|"key in whitelist"| H["Include in gemini_params"]
    G -->|"key NOT in whitelist\ne.g. max_tokens, temperature"| I["Drop param ❌"]
    H --> J{"Which endpoint?"}
    J -->|"Text input"| K["transform_openai_input_gemini_content\n→ batchEmbedContents"]
    J -->|"Multimodal input"| L["transform_openai_input_gemini_embed_content\n→ embedContent"]
    K --> M["EmbedContentRequest(**gemini_params)\nNo 400 BadRequestError"]
    L --> N["request_body dict(**gemini_params)\nNo 400 BadRequestError"]
Loading

Reviews (1): Last reviewed commit: "fix(gemini): filter unsupported params f..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing Chesars:fix/gemini-embedding-drop-unsupported-params (db0d85e) with main (c89496f)

Open in CodSpeed

@Chesars
Chesars changed the base branch from main to litellm_staging_03_22_2026 March 22, 2026 21:45
@Chesars Chesars changed the title fix(gemini): filter unsupported params from embedding requests fix(gemini): filter params from embedding requests Mar 22, 2026
@Chesars
Chesars merged commit 335f4e8 into BerriAI:litellm_staging_03_22_2026 Mar 22, 2026
38 of 39 checks passed
@Chesars
Chesars deleted the fix/gemini-embedding-drop-unsupported-params branch March 22, 2026 21:46
Chesars added a commit that referenced this pull request Apr 16, 2026
- streaming_iterator.py: adopted main's more defensive version of the
  tool-arg queueing check (.get() instead of [], isinstance guard) —
  same logic, same behavior, lower crash surface
- model_prices_and_context_window.json + backup: combined staging's
  search_context_cost_per_query fields (PR #24372) with main's new
  supports_service_tier field — both are independent additions to the
  same Gemini model entries
- test_streaming_handler.py: kept Azure streaming regression test
  (PR #24354) and added main's two new Gemini legacy vertex
  finish_reason normalization tests
- test_gemini_batch_embeddings.py: kept staging's unsupported-params
  filtering tests (PR #24370) and added main's index/order test
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…op-unsupported-params

fix(gemini): filter unsupported params from embedding requests
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
- streaming_iterator.py: adopted main's more defensive version of the
  tool-arg queueing check (.get() instead of [], isinstance guard) —
  same logic, same behavior, lower crash surface
- model_prices_and_context_window.json + backup: combined staging's
  search_context_cost_per_query fields (PR BerriAI#24372) with main's new
  supports_service_tier field — both are independent additions to the
  same Gemini model entries
- test_streaming_handler.py: kept Azure streaming regression test
  (PR BerriAI#24354) and added main's two new Gemini legacy vertex
  finish_reason normalization tests
- test_gemini_batch_embeddings.py: kept staging's unsupported-params
  filtering tests (PR BerriAI#24370) and added main's index/order test
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]: Gemini embedding batch request sends max_tokens causing 400 BadRequestError

1 participant