litellm - ✅(Solved) Fix [Bug]: Custom LLM providers silently bypassed when model name matches built-in provider [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#23352Fetched 2026-04-08 00:37:14
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
labeled ×3cross-referenced ×1

Error Message

Custom LLM providers registered via custom_provider_map are silently bypassed when the underlying model name (after prefix stripping by get_llm_provider()) matches a known built-in model. The request goes directly to the built-in provider (e.g. OpenAI) instead of the custom handler. No error is raised.

Root Cause

In litellm/main.py, the completion() function has a long if/elif dispatch chain. get_llm_provider() strips the custom provider prefix (mcs-provider/gpt-5.4gpt-5.4), and then the branch at ~line 2524:

elif (
    model in litellm.open_ai_chat_completion_models  # "gpt-5.4" matches here!
    or custom_llm_provider == "openai"
    ...
):

is reached before the custom provider check at ~line 4282:

elif (
    custom_llm_provider in litellm._custom_providers  # never reached
):

This affects any custom provider that routes to a model name known to any built-in provider (OpenAI, Anthropic, Cohere, etc.).

Fix Action

Fix

Move the _custom_providers dispatch block to the top of the if/elif chain — before all built-in provider checks. Explicitly registered custom providers should always take priority.

I have a PR ready with this fix.

PR fix notes

PR #23353: fix: move custom provider dispatch before model-name-based matching

Description (problem / solution / changelog)

🐛 Bug Fix

Summary

Fixes: https://github.com/BerriAI/litellm/issues/23352

Custom LLM providers registered via custom_provider_map are silently bypassed when the model name (after prefix stripping by get_llm_provider()) matches a known built-in model like gpt-5.4 or claude-sonnet-4-6.

Root Cause

The if/elif dispatch chain in completion() checks model in litellm.open_ai_chat_completion_models before custom_llm_provider in litellm._custom_providers. Since get_llm_provider() strips the provider prefix (my-provider/gpt-5.4gpt-5.4), the naked model name matches the OpenAI catch-all branch, and the custom handler is never reached.

Changes

Move the _custom_providers dispatch block to the top of the if/elif chain in completion(), before all built-in provider checks. Explicitly registered custom providers should always take priority over implicit model-name matching.

Test Plan

  • Register a custom provider that proxies gpt-5.4 via wildcard routing (mcs/*mcs-provider/*)
  • Verify the custom handler's acompletion is called (previously silently bypassed)
  • Verify non-custom provider models (e.g. direct openai/gpt-5.4) still work
  • Existing unit tests pass (make test-unit)

Changed files

  • litellm/main.py (modified, +51/-49)

Code Example

from litellm.llms.custom_llm import CustomLLM
from litellm.utils import ModelResponse

class MCSProvider(CustomLLM):
    async def acompletion(self, model, messages, model_response, **kwargs) -> ModelResponse:
        # This method is NEVER called
        model_response.choices[0].message.content = "Hello from custom provider"
        model_response.choices[0].finish_reason = "stop"
        return model_response

mcs_handler = MCSProvider()

---

model_list:
  - model_name: "mcs/*"
    litellm_params:
      model: "mcs-provider/*"

litellm_settings:
  custom_provider_map:
    - {"provider": "mcs-provider", "custom_handler": "mcs_provider.mcs_handler"}

---

litellm --config config.yaml --port 4000

curl http://localhost:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "mcs/gpt-5.4", "messages": [{"role": "user", "content": "Hi"}]}'

---

elif (
    model in litellm.open_ai_chat_completion_models  # "gpt-5.4" matches here!
    or custom_llm_provider == "openai"
    ...
):

---

elif (
    custom_llm_provider in litellm._custom_providers  # never reached
):

---
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

Bug Description

Custom LLM providers registered via custom_provider_map are silently bypassed when the underlying model name (after prefix stripping by get_llm_provider()) matches a known built-in model. The request goes directly to the built-in provider (e.g. OpenAI) instead of the custom handler. No error is raised.

Fix

Move the _custom_providers dispatch block to the top of the if/elif chain — before all built-in provider checks. Explicitly registered custom providers should always take priority.

I have a PR ready with this fix.

Steps to Reproduce

1. Custom provider (mcs_provider.py)

from litellm.llms.custom_llm import CustomLLM
from litellm.utils import ModelResponse

class MCSProvider(CustomLLM):
    async def acompletion(self, model, messages, model_response, **kwargs) -> ModelResponse:
        # This method is NEVER called
        model_response.choices[0].message.content = "Hello from custom provider"
        model_response.choices[0].finish_reason = "stop"
        return model_response

mcs_handler = MCSProvider()

2. Config (config.yaml)

model_list:
  - model_name: "mcs/*"
    litellm_params:
      model: "mcs-provider/*"

litellm_settings:
  custom_provider_map:
    - {"provider": "mcs-provider", "custom_handler": "mcs_provider.mcs_handler"}

3. Test

litellm --config config.yaml --port 4000

curl http://localhost:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "mcs/gpt-5.4", "messages": [{"role": "user", "content": "Hi"}]}'

Expected: Response comes from the custom handler. Actual: Response comes directly from OpenAI. The custom handler is never called.

Root Cause

In litellm/main.py, the completion() function has a long if/elif dispatch chain. get_llm_provider() strips the custom provider prefix (mcs-provider/gpt-5.4gpt-5.4), and then the branch at ~line 2524:

elif (
    model in litellm.open_ai_chat_completion_models  # "gpt-5.4" matches here!
    or custom_llm_provider == "openai"
    ...
):

is reached before the custom provider check at ~line 4282:

elif (
    custom_llm_provider in litellm._custom_providers  # never reached
):

This affects any custom provider that routes to a model name known to any built-in provider (OpenAI, Anthropic, Cohere, etc.).

Relevant log output

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

v1.82.1

Twitter / LinkedIn details

www.linkedin.com/in/dannygerst/

extent analysis

Fix Plan

To fix the issue, we need to modify the completion() function in litellm/main.py to prioritize custom providers.

  1. Move the custom provider check: Move the _custom_providers dispatch block to the top of the if/elif chain, before all built-in provider checks.
  2. Update the condition: Ensure the condition checks for the custom provider before stripping the prefix.

Example code:

# Check for custom providers first
if custom_llm_provider in litellm._custom_providers:
    # Call the custom provider
    return litellm._custom_providers[custom_llm_provider].acompletion(model, messages, model_response, **kwargs)

# ... rest of the if/elif chain ...

Alternatively, you can also modify the get_llm_provider() function to check for custom providers before stripping the prefix.

Verification

To verify the fix, follow these steps:

  1. Apply the code changes.
  2. Restart the litellm server.
  3. Run the test again using the curl command.
  4. Check the response to ensure it comes from the custom handler.

Extra Tips

  • Make sure to update the custom_provider_map in the config.yaml file to include the custom provider.
  • If you have multiple custom providers, ensure they are properly registered and prioritized in the _custom_providers dictionary.
  • Consider adding logging or debugging statements to verify the custom provider is being called correctly.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING