Skip to content

fix(gemini): avoid duplicate model route for full api_base#26980

Closed
StatPan wants to merge 6 commits into
BerriAI:mainfrom
StatPan:fix/gemini-full-api-base-duplicate-path
Closed

fix(gemini): avoid duplicate model route for full api_base#26980
StatPan wants to merge 6 commits into
BerriAI:mainfrom
StatPan:fix/gemini-full-api-base-duplicate-path

Conversation

@StatPan
Copy link
Copy Markdown

@StatPan StatPan commented May 1, 2026

Summary

  • avoid appending a duplicate /models/{model}:{endpoint} route when Gemini api_base already includes the full route
  • handle api_base values that already end with /models/{model} by appending only :{endpoint}
  • add regression coverage for full-route and model-prefix custom api_base cases

Context

This is a follow-up/replacement for #24786, which has been inactive since 2026-03-30.

The bug is still affecting downstream integrations in OpenHands:

Tracking issue:

Test Plan

  • uv run pytest tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py -k 'custom_proxy or full_route or api_base'
  • uv run ruff check litellm/llms/vertex_ai/vertex_llm_base.py tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py

harish-berri and others added 5 commits April 29, 2026 20:14
…ags.

Add tests to validate the condition

 improve the conditional readability by naming the plain-tag check explicitly.
…_based_routing

add test(tag-routing): prevent header regex bypass for strict plain t…
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 1, 2026

CLA assistant check
All committers have signed the CLA.

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 1, 2026

Note: the initial branch-guard check is failing because this repo currently rejects external fork PRs to main and instructs contributors to target litellm_oss_branch, but that branch does not appear to exist.

I'm leaving the PR open since the code/tests are here and the rest of CI is running, but if maintainers want this retargeted another way I can adjust quickly.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 1, 2026

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing StatPan:fix/gemini-full-api-base-duplicate-path (f981e4a) with main (934ecdc)

Open in CodSpeed

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 1, 2026

For clarity on the current failing checks:

  • Guard main branch / Verify PR source branch is failing because this PR comes from an external fork, and the workflow currently blocks fork -> main PRs.
  • Check Lazy OpenAPI Snapshot / verify is also failing in the fork context with Resource not accessible by integration while trying to mark the check neutral.

These two failures do not appear to be caused by the Gemini fix itself. I'm watching the provider test jobs separately for actual code-level regressions.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 1, 2026

Greptile Summary

This PR fixes a duplicate-route bug in _check_custom_proxy where Gemini api_base values that already contain /models/{model}:{endpoint} (or just /models/{model}) would have another /models/{model}:{endpoint} segment appended, producing broken URLs. A rstrip("/") on the fallback path also prevents double-slash issues. The tag_based_routing.py change is a cosmetic no-op (see inline comment) and both test files are well-scoped with no network calls.

Confidence Score: 4/5

Safe to merge; the core Gemini URL-construction fix is correct and well-covered by new tests.

No P0/P1 findings. One P2 edge case in the URL-construction logic and one P2 noting the tag-routing change is functionally a no-op. Both are non-blocking.

litellm/llms/vertex_ai/vertex_llm_base.py — edge case where api_base ends with /models/{model}:{different_endpoint}

Important Files Changed

Filename Overview
litellm/llms/vertex_ai/vertex_llm_base.py Core bug fix: adds three-way branching to avoid double-appending /models/{model}:{endpoint} when api_base already carries the full route. One unhandled edge case remains: an api_base ending with /models/{model}:{different_endpoint} falls through to the else branch and produces a broken double-path URL.
litellm/router_strategy/tag_based_routing.py Cosmetic refactor: replaces bool(deployment_tags) with an explicit is not None and len(...) > 0 guard. Functionally identical to the original for all valid deployment_tags values.
tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py Adds three parametrized cases covering full-route, model-only, and plain-base api_base inputs; strengthens an existing test by replacing a print with a proper assert; removes unused imports.
tests/test_litellm/router_strategy/test_router_tag_routing.py Adds a new test verifying that strict-tag mode (match_any=False) blocks regex-based routing when request_tags is None. Correct and well-named, though the underlying production code change is a no-op.

Reviews (1): Last reviewed commit: "test(gemini): cover full-route custom ap..." | Re-trigger Greptile

Comment on lines +415 to +422
if api_base.endswith(f"/models/{model}:{endpoint}"):
url = api_base
elif api_base.endswith(f"/models/{model}"):
url = f"{api_base}:{endpoint}"
else:
url = "{}/models/{}:{}".format(
api_base.rstrip("/"), model, endpoint
)
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.

P2 Unhandled edge case: api_base ends with a different endpoint suffix

If api_base already contains a full route but with a different endpoint — e.g. https://proxy.example.com/.../models/gemini-2.5-flash-lite:streamGenerateContent while the current call has endpoint="generateContent" — neither condition 1 nor 2 matches. The else branch then appends /models/gemini-2.5-flash-lite:generateContent to the existing full URL, producing a doubly-routed, broken URL. Admittedly an unlikely proxy configuration, but it may silently produce a 404 instead of a clear error.

Comment on lines +109 to +110
deployment_has_plain_tags = deployment_tags is not None and len(deployment_tags) > 0
strict_tag_check_failed = not match_any and deployment_has_plain_tags
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.

P2 Refactor is functionally equivalent to the original

bool(deployment_tags) and deployment_tags is not None and len(deployment_tags) > 0 produce identical results for all possible values of deployment_tags (None, [], or a non-empty list). The accompanying test test_strict_tag_routing_without_request_tags_blocks_header_regex_fallback also passes against the original code, so this change does not fix any behavioral bug — it only clarifies intent. If not intentional, the PR description is slightly misleading.

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 1, 2026

I found and fixed the Vertex AI test failure.

Root cause: while cleaning up the test file, I accidentally changed the expected value in test_credential_project_validation for the different-project case. That was unrelated to the Gemini api_base fix and caused the Vertex AI suite regression.

I've pushed a follow-up commit restoring the original expectation and re-ran the affected tests locally:

  • uv run pytest tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py::TestVertexBase::test_credential_project_validation -v
  • uv run pytest tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py -k "custom_proxy or full_route or api_base or credential_project_validation"
  • uv run ruff check litellm/llms/vertex_ai/vertex_llm_base.py tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 1, 2026

Documenting the remaining blocker clearly:

This PR is now down to a single failing required check: Guard main branch / Verify PR source branch.

Root cause is repository contribution routing policy, not the Gemini fix itself:

  • HEAD_REPO = StatPan/litellm
  • BASE_REPO = BerriAI/litellm
  • HEAD_REF = fix/gemini-full-api-base-duplicate-path
  • BASE_REF = main

The workflow only allows PRs into main when they come from the canonical repo (BerriAI/litellm) and from an internal branch such as litellm_internal_staging or litellm_hotfix_*. Because this PR comes from an external fork and targets main, the guard fails before mergeability can be evaluated on code alone.

So at this point the code/tests are green; the remaining blocker is that this change likely needs to be retargeted through the repo's OSS staging flow rather than submitted directly to main. Based on recent contributor PRs, litellm_oss_staging appears to be the closest match for that path.

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 1, 2026

I've re-opened the same fix through the OSS staging path here: #26982

Reason for replacement: #26980 is code/test green but blocked by the repo's Guard main branch / Verify PR source branch policy because it targets main from an external fork.

Keeping #26980 as the routing/reference record and moving the actionable merge path to #26982 (base=litellm_oss_staging).

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 1, 2026

Final clean actionable PR is now #26983.

Keeping this PR as the original main-target routing record only. The merge path should be reviewed on #26983, which is rebuilt from litellm_oss_staging with a minimal 2-file diff.

@StatPan
Copy link
Copy Markdown
Author

StatPan commented May 14, 2026

Closing as superseded by the clean actionable PR #26983. This PR is kept only as the original main-target routing record; #26983 has the minimal 2-file diff against .

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.

4 participants