crewAIInc/crewAI · error · ValueError

provider is required

Error message

provider is required

What it means

Thrown by normalize_provider() in crewai_files.formatting.api when the provider argument is None or an empty string. The library needs a provider name to select the correct formatter (gemini, google, anthropic, claude, bedrock, etc.), so it refuses to guess and raises ValueError('provider is required'). It is a caller-side programming error, not an environment issue.

Source

Thrown at lib/crewai-files/src/crewai_files/formatting/api.py:36

from crewai_files.processing.processor import FileProcessor
from crewai_files.resolution.resolver import FileResolver, FileResolverConfig
from crewai_files.uploaders.factory import ProviderType


def _normalize_provider(provider: str | None) -> ProviderType:
    """Normalize provider string to ProviderType.

    Args:
        provider: Raw provider string.

    Returns:
        Normalized provider type.

    Raises:
        ValueError: If provider is None or empty.
    """
    if not provider:
        raise ValueError("provider is required")

    provider_lower = provider.lower()

    if "gemini" in provider_lower:
        return "gemini"
    if "google" in provider_lower:
        return "google"
    if "anthropic" in provider_lower:
        return "anthropic"
    if "claude" in provider_lower:
        return "claude"
    if "bedrock" in provider_lower:
        return "bedrock"
    if "aws" in provider_lower:
        return "aws"
    if "azure" in provider_lower:
        return "azure"
    if "gpt" in provider_lower:

View on GitHub (pinned to 754d7323be)

Solutions

  1. Pass a non-empty provider string such as "anthropic", "openai", "google", "gemini", "bedrock" or "vertex_ai" (matching is case-insensitive substring based).
  2. If the provider comes from config, give it a default: provider = config.get("provider") or "openai".
  3. Validate at the boundary of your app (fail fast on startup) rather than deep in the formatting call.
  4. Add a unit test asserting ValueError is raised for None/empty so the contract stays locked.

Example fix

// before
provider = config.get("provider")  # None when key missing
formatter = get_formatter(provider, ...)

# after
provider = config.get("provider")
if not provider:
    raise ValueError("config must define 'provider'")
formatter = get_formatter(provider, ...)
Defensive patterns

Strategy: validation

Validate before calling

provider = config.get("provider")
if not provider or not provider.strip():
    raise ValueError("config must define a non-empty 'provider'")

Type guard

def is_valid_provider(provider: object) -> TypeGuard[str]:
    return isinstance(provider, str) and bool(provider.strip())

Try / catch

try:
    formatter_api = build(provider)
except ValueError as e:
    if "provider is required" in str(e):
        raise ConfigError("LLM provider not configured") from e
    raise

Prevention

When it happens

Trigger: Calling the formatting API entry point with provider=None, provider="", or provider=" " (any falsy value; note whitespace-only strings pass this check but then fall through the substring matching). Typically happens when the provider is read from an optional config field or dict that was never populated.

Common situations: Optional provider key missing from a config dict (config.get("provider") returns None); env var like os.environ.get("LLM_PROVIDER") unset; a default parameter left as None and forwarded unchecked; refactoring that dropped the provider argument.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/f11d0ca2fd2b86eb. Report an issue: GitHub.