HKUDS/DeepTutor · error · LLMConfigError

Model is required

Error message

Model is required

What it means

The routing provider delegates to local_provider/cloud_provider and needs a model name; neither the `model` kwarg nor the routing config's `model` field provided one. It raises LLMConfigError before attempting any API call, so no network traffic occurs.

Source

Thrown at deeptutor/services/llm/providers/routing.py:80

def _coerce_str(value: object, default: str) -> str:
    return value if isinstance(value, str) and value else default


@register_provider("routing")
class RoutingProvider(BaseLLMProvider):
    """Provider that routes between cloud and local function providers."""

    def __init__(self, config: LLMConfig) -> None:
        super().__init__(config)
        # Use per-route provider name for circuit-breaker/metrics when possible.
        if is_local_llm_server(self.base_url or ""):
            self.provider_name = "local"

    async def complete(self, prompt: str, **kwargs: object) -> TutorResponse:
        """Complete via local_provider/cloud_provider with retries."""
        model = _coerce_str(kwargs.pop("model", None), self.config.model)
        if not model:
            raise LLMConfigError("Model is required")

        system_prompt = kwargs.pop("system_prompt", "You are a helpful assistant.")
        messages = kwargs.pop("messages", None)
        max_retries = _coerce_int(kwargs.pop("max_retries", 3), 3)
        sleep_value = kwargs.pop("sleep", None)
        sleep = sleep_value if callable(sleep_value) else None

        use_cache = bool(kwargs.pop("use_cache", True))
        cache_ttl_seconds = kwargs.pop("cache_ttl_seconds", None)
        cache_key = kwargs.pop("cache_key", None)

        call_kwargs = {
            "prompt": prompt,
            "system_prompt": system_prompt,
            "model": model,
            "api_key": self.api_key,
            "base_url": self.base_url,
            "messages": messages,

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Set a default model on the routing provider's config.
  2. Pass model="..." in the complete() kwargs.
  3. Verify the settings file (data/user/settings) for the routing/local provider actually contains a model key.

Example fix

# before
await router.complete("hi")  # LLMConfigError

# after
await router.complete("hi", model="llama3.1")
Defensive patterns

Strategy: validation

Validate before calling

if not (kwargs.get("model") or router.config.model):
    raise LLMConfigError("Model is required")

Type guard

def _coerce_str(v, default):
    if isinstance(v, str) and v.strip():
        return v
    return default

Try / catch

from deeptutor.services.llm.errors import LLMConfigError
try:
    resp = await router.complete(prompt, model=resolved_model)
except LLMConfigError:
    # config problem — fix settings, do not retry
    raise

Prevention

When it happens

Trigger: Calling RoutingProvider.complete() when the routing config has no default model and the caller omits model=...; the underlying local provider config (e.g. Ollama) was expected to supply a default but routing doesn't read it.

Common situations: Misconfigured routing settings JSON where "model" is absent, migrating configs after a schema change, assuming the local backend's default model propagates to the router.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/0c0e5ece7ee1ce88. Report an issue: GitHub.