assafelovic/gpt-researcher · error · ValueError

Model cannot be None

Error message

Model cannot be None

What it means

create_chat_completion validates its inputs and raises ValueError when the model argument is None. This is a guard against misconfiguration: the LLM layer must know which model to call, and passing None usually means a config key (FAST_LLM/SMART_LLM/STRATEGIC_LLM) was never resolved from settings or env vars.

Source

Thrown at gpt_researcher/utils/llm.py:72

    """Create a chat completion using the OpenAI API
    Args:
        messages (list[dict[str, str]]): The messages to send to the chat completion.
        model (str, optional): The model to use. Defaults to None.
        temperature (float, optional): The temperature to use. Defaults to 0.4.
        max_tokens (int, optional): The max tokens to use. Defaults to 4000.
        llm_provider (str, optional): The LLM Provider to use.
        stream (bool): Whether to stream the response. Defaults to False.
        webocket (WebSocket): The websocket used in the currect request,
        llm_kwargs (dict[str, Any], optional): Additional LLM keyword arguments. Defaults to None.
        cost_callback: Callback function for updating cost.
        reasoning_effort (str, optional): Reasoning effort for OpenAI's reasoning models. Defaults to 'low'.
        **kwargs: Additional keyword arguments.
    Returns:
        str: The response from the chat completion.
    """
    # validate input
    if model is None:
        raise ValueError("Model cannot be None")
    # Sanity guard against absurd values (e.g., env var typos). The actual
    # per-model output limits are enforced by the upstream provider.
    if max_tokens is not None and max_tokens > 200_000:
        raise ValueError(
            f"max_tokens={max_tokens} exceeds the largest output limit of "
            "any currently available model (128k as of late 2025). "
            "Check your FAST_TOKEN_LIMIT / SMART_TOKEN_LIMIT / "
            "STRATEGIC_TOKEN_LIMIT env vars for typos."
        )

    # Get the provider from supported providers
    provider_kwargs = {'model': model}

    if llm_kwargs:
        provider_kwargs.update(llm_kwargs)
    elif os.environ.get("LLM_KWARGS"):
        import json
        try:

View on GitHub (pinned to 6f998577d5)

Solutions

  1. Set the model explicitly in config: FAST_LLM, SMART_LLM, STRATEGIC_LLM (and LLM_PROVIDER) env vars or Config attributes
  2. If calling directly, pass a concrete model string: create_chat_completion(..., model='gpt-4o-mini')
  3. Inspect your Config instance right before the call: print(cfg.fast_llm_model, cfg.smart_llm_model, cfg.strategic_llm_model)
  4. When subclassing Config, ensure you don't shadow llm attributes with None defaults

Example fix

# before
response = await create_chat_completion(prompt, None)  # ValueError: Model cannot be None

# after
response = await create_chat_completion(prompt, cfg.fast_llm_model or 'gpt-4o-mini')
Defensive patterns

Strategy: type-guard

Validate before calling

model = cfg.fast_llm_model or cfg.smart_llm_model
assert model, 'LLM model is unset — check FAST_LLM/SMART_LLM config'

Type guard

def has_model(model) -> bool:
    return isinstance(model, str) and bool(model.strip())

Try / catch

try:
    resp = await create_chat_completion(prompt, model)
except ValueError as e:
    if 'Model cannot be None' in str(e):
        resp = await create_chat_completion(prompt, 'gpt-4o-mini')
    else:
        raise

Prevention

When it happens

Trigger: Calling create_chat_completion(..., model=None), typically because cfg.fast_llm_model / smart_llm / strategic returned None — e.g. a custom Config subclass that didn't populate llm settings, or a direct call where the model param was omitted/misnamed.

Common situations: Building a custom Config object and forgetting to set the LLM provider/model fields; upgrading gpt-researcher where config attribute names changed; passing kwargs like model_name= instead of model=.

Related errors


AI-assisted analysis of assafelovic/gpt-researcher@6f998577d5 (2026-08-28). Data as JSON: /api/errors/ea90d63f8cdaffb2. Report an issue: GitHub.