Skip to content

exceptions

Outlines exception hierarchy and per-provider normalization.

All public exceptions inherit from APIErrorOutlinesErrorException. Use :func:normalize_provider_exception to convert a raw provider SDK exception into the appropriate Outlines type.

APIConnectionError

Bases: APIError

Unreachable host, DNS failure, or refused connection.

Source code in outlines/exceptions.py
class APIConnectionError(APIError):
    """Unreachable host, DNS failure, or refused connection."""
    retryable = True
    hint = "Could not reach provider, check connection."

APIError

Bases: OutlinesError

Base class for all provider API errors raised by Outlines.

Subclasses map to specific HTTP status codes or failure categories (see the hierarchy below). Catch this class to handle any provider error generically, or catch a subclass for finer-grained control.

Attributes:

Name Type Description
provider str | None

Short provider name, e.g. "openai" or "anthropic".

original_exception Exception | None

The raw SDK exception that was caught, preserved for debugging.

status_code int | None

HTTP status code, if one could be extracted from the exception.

request_id str | None

Provider request ID extracted from the exception or response headers, useful when filing bug reports with a provider.

retryable bool

True for transient errors worth retrying (rate limits, timeouts, 5xx server errors, connection failures). False for permanent errors that require fixing the request or credentials.

hint str

Short human-readable suggestion. On Python 3.11+ this is attached via add_note() and displayed as → <hint> on its own line in tracebacks; on 3.10 it is stored as _hint_note.

Source code in outlines/exceptions.py
class APIError(OutlinesError):
    """Base class for all provider API errors raised by Outlines.

    Subclasses map to specific HTTP status codes or failure categories
    (see the hierarchy below). Catch this class to handle any provider
    error generically, or catch a subclass for finer-grained control.

    Attributes
    ----------
    provider : str | None
        Short provider name, e.g. ``"openai"`` or ``"anthropic"``.
    original_exception : Exception | None
        The raw SDK exception that was caught, preserved for debugging.
    status_code : int | None
        HTTP status code, if one could be extracted from the exception.
    request_id : str | None
        Provider request ID extracted from the exception or response headers,
        useful when filing bug reports with a provider.
    retryable : bool
        ``True`` for transient errors worth retrying (rate limits, timeouts,
        5xx server errors, connection failures). ``False`` for permanent errors
        that require fixing the request or credentials.
    hint : str
        Short human-readable suggestion. On Python 3.11+ this is attached via
        ``add_note()`` and displayed as ``  → <hint>`` on its own line in
        tracebacks; on 3.10 it is stored as ``_hint_note``.
    """

    retryable: bool = False  # overridden to True on transient error subclasses
    hint: str = ""           # overridden on each subclass with actionable advice

    def __init__(
        self,
        message: str | None = None,
        provider: str | None = None,
        original_exception: Exception | None = None,
        status_code: int | None = None,
        request_id: str | None = None,
    ):
        if message is None:
            if provider and original_exception is not None:
                message = f"API Error [{provider}]: {original_exception}"
            elif provider:
                message = f"API Error [{provider}]"
            elif original_exception is not None:
                message = f"API error: {original_exception}"
            else:
                message = "API error"

        super().__init__(message)

        # PEP 678 (Python 3.11+): notes appear on their own line in tracebacks
        if self.hint:
            note = f"  → {self.hint}"
            if hasattr(self, "add_note"):  # Python 3.11+
                self.add_note(note)
            else:
                self._hint_note = note

        self.provider = provider
        self.original_exception = original_exception
        self.status_code = status_code or _extract_status_code(original_exception)
        self.request_id = request_id

        if original_exception is not None:
            self.request_id = self.request_id or _extract_request_id(original_exception)

APITimeoutError

Bases: APIError

Request or connect timeout.

Source code in outlines/exceptions.py
class APITimeoutError(APIError):
    """Request or connect timeout."""
    retryable = True
    hint = "Provider may be overloaded."

AuthenticationError

Bases: APIError

401 - bad or missing API key.

Source code in outlines/exceptions.py
class AuthenticationError(APIError):
    """401 - bad or missing API key."""
    hint = "Check API key."

BadRequestError

Bases: APIError

400, 409, 413, 422, other 4xx - malformed request.

Source code in outlines/exceptions.py
class BadRequestError(APIError):
    """400, 409, 413, 422, other 4xx - malformed request."""
    hint = (
        "Check prompt length, schema, unsupported parameters, etc. "
        "If this is a provider schema support error, try a local model or dottxt."
    )

GenerationError

Bases: APIError

Content filter hit, length stop, or refusal.

Source code in outlines/exceptions.py
class GenerationError(APIError):
    """Content filter hit, length stop, or refusal."""
    hint = "Output was refused, hit a content filter, reached the model's max-token limit, or similar."

NotFoundError

Bases: APIError

404 - wrong model name or endpoint.

Source code in outlines/exceptions.py
class NotFoundError(APIError):
    """404 - wrong model name or endpoint."""
    hint = "Confirm model name, endpoint, etc."

PermissionDeniedError

Bases: APIError

403 - valid key, insufficient scope.

Source code in outlines/exceptions.py
class PermissionDeniedError(APIError):
    """403 - valid key, insufficient scope."""
    hint = "Check permissions for API key."

ProviderResponseError

Bases: APIError

Malformed or unparseable response from the provider.

Source code in outlines/exceptions.py
class ProviderResponseError(APIError):
    """Malformed or unparseable response from the provider."""
    hint = "May be a temporary issue or schema/format mismatch."

RateLimitError

Bases: APIError

429 - rate limit exceeded.

Source code in outlines/exceptions.py
class RateLimitError(APIError):
    """429 - rate limit exceeded."""
    retryable = True
    hint = "Slow down and retry, or reduce request frequency, batch size, etc."

ServerError

Bases: APIError

500-599, Anthropic 529 - server-side failure.

Source code in outlines/exceptions.py
class ServerError(APIError):
    """500-599, Anthropic 529 - server-side failure."""
    retryable = True
    hint = "Perhaps retry after a short wait."

is_provider_exception(exc, provider)

Return True only for provider/transport exceptions we expect to normalize.

This prevents programmer errors (TypeError, AttributeError, etc.) from being silently re-labeled as APIError.

  1. If the exception matches the provider's explicit SDK map → True.
  2. If the exception carries an HTTP status code → True (covers SDK base classes not listed individually, e.g. ollama.ResponseError).
  3. Otherwise → False (let it propagate as-is).
Source code in outlines/exceptions.py
def is_provider_exception(exc: Exception, provider: str) -> bool:
    """Return ``True`` only for provider/transport exceptions we expect to normalize.

    This prevents programmer errors (``TypeError``, ``AttributeError``, etc.)
    from being silently re-labeled as ``APIError``.

    1. If the exception matches the provider's explicit SDK map → True.
    2. If the exception carries an HTTP status code → True (covers SDK base
       classes not listed individually, e.g. ``ollama.ResponseError``).
    3. Otherwise → False (let it propagate as-is).
    """
    exc_map = _build_exception_map(provider)
    if isinstance(exc, tuple(exc_map.keys())):
        return True
    return _extract_status_code(exc) is not None

normalize_provider_errors(provider)

Normalize provider exceptions raised inside this block.

This is a context manager instead of a decorator so wrappers can use the same helper around sync calls, awaited async calls, sync generators, async generators, and other provider SDK control-flow shapes without needing separate wrapper machinery for each function kind.

Source code in outlines/exceptions.py
@contextmanager
def normalize_provider_errors(provider: str) -> Iterator[None]:
    """Normalize provider exceptions raised inside this block.

    This is a context manager instead of a decorator so wrappers can use the
    same helper around sync calls, awaited async calls, sync generators, async
    generators, and other provider SDK control-flow shapes without needing
    separate wrapper machinery for each function kind.
    """
    try:
        yield
    except Exception as exc:
        if not is_provider_exception(exc, provider):
            raise
        raise normalize_provider_exception(exc, provider) from exc

normalize_provider_exception(exc, provider)

Map a provider SDK exception to the appropriate Outlines exception.

  1. Try the provider's SDK exception map (most-specific-first via isinstance).
  2. Fall back to status-code inspection on the original exception.
  3. Default to generic APIError.
Source code in outlines/exceptions.py
def normalize_provider_exception(exc: Exception, provider: str) -> APIError:
    """Map a provider SDK exception to the appropriate Outlines exception.

    1. Try the provider's SDK exception map (most-specific-first via isinstance).
    2. Fall back to status-code inspection on the original exception.
    3. Default to generic APIError.
    """
    for provider_exc_cls, outlines_exc_cls in _build_exception_map(provider).items():
        if isinstance(exc, provider_exc_cls):
            return outlines_exc_cls(provider=provider, original_exception=exc)

    code = _extract_status_code(exc)
    if code is not None:
        if code in _STATUS_CODE_MAP:
            return _STATUS_CODE_MAP[code](provider=provider, original_exception=exc)
        if code >= 500:
            return ServerError(provider=provider, original_exception=exc)
        if 400 <= code < 500:
            return BadRequestError(provider=provider, original_exception=exc)

    return APIError(provider=provider, original_exception=exc)