HKUDS/DeepTutor · error · LLMConfigError

Model not configured for OpenAI provider

Error message

Model not configured for OpenAI provider

What it means

The OpenAI provider was constructed without a model: config resolution yielded no default model name, and unlike auto-model providers this wrapper requires an explicit model for every call. The sentinel text is raised wherever the model is first needed.

Solutions

  1. Set model in the LLMConfig used to construct the provider (e.g. 'gpt-4o-mini').
  2. Or pass model=... per call: complete(prompt, model='gpt-4o-mini').
  3. Check the provider/catalog settings for an empty model field.

Example fix

# before
resp = await provider.complete('hi')  # config.model is None
# after
resp = await provider.complete('hi', model='gpt-4o-mini')
Defensive patterns

Strategy: validation

Validate before calling

def openai_complete_ready(config, kwargs: dict) -> bool:
    return bool(kwargs.get('model') or getattr(config, 'model', None))

Try / catch

try:
    resp = await provider.complete(prompt)
except LLMConfigError as e:
    if 'Model not configured' in str(e):
        resp = await provider.complete(prompt, model=DEFAULT_MODEL)
    else:
        raise

Prevention

When it happens

Trigger: Calling OpenAIProvider.complete(prompt) with no model kwarg when config.model is None/'' — e.g. a settings entry or LLMConfig built without a model field.

Common situations: Default LLMConfig() never populated with a model; catalog entry missing the model name after migrations; code paths that previously defaulted model now hitting the explicit guard.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at deeptutor/services/llm/providers/open_ai.py:77

        super().__init__(config)
        http_client = None
        if load_system_settings()["disable_ssl_verify"]:
            if os.getenv("ENVIRONMENT", "").lower() in ("prod", "production"):
                raise LLMConfigError("DISABLE_SSL_VERIFY is not allowed in production")
            logger.warning("SSL verification disabled for OpenAI HTTP client")
            http_client = httpx.AsyncClient(verify=False)  # nosec B501
        self.client = openai.AsyncOpenAI(
            api_key=self.api_key,
            base_url=self.base_url or None,
            http_client=http_client,
        )

    @_typed_track_llm_call("openai")
    async def complete(self, prompt: str, **kwargs: object) -> TutorResponse:
        model_raw = kwargs.pop("model", None)
        model = model_raw if isinstance(model_raw, str) and model_raw else self.config.model
        if not model:
            raise LLMConfigError("Model not configured for OpenAI provider")
        kwargs.pop("stream", None)

        requested_max_tokens = (
            kwargs.pop("max_tokens", None)
            or kwargs.pop("max_completion_tokens", None)
            or getattr(self.config, "max_tokens", 4096)
        )
        if isinstance(requested_max_tokens, (int, float, str)):
            max_tokens = int(requested_max_tokens)
        else:
            max_tokens = int(getattr(self.config, "max_tokens", 4096))
        kwargs.update(get_token_limit_kwargs(model, max_tokens))

        async def _call_api() -> TutorResponse:
            request_kwargs: dict[str, object] = dict(kwargs)
            response = await self.client.chat.completions.create(  # type: ignore[call-overload]
                model=model,
                messages=[{"role": "user", "content": prompt}],

View on GitHub (pinned to 3e82f13042)