# How Open Notebook's Error Classification System Translates LLM Provider Exceptions to User-Friendly Messages

> Open Notebook's error classification system simplifies LLM provider exceptions. Discover how it translates technical errors like HTTP 401 into actionable user messages.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-07-04

---

**Open Notebook centralizes LLM provider exception handling through the `classify_error` utility in [`open_notebook/utils/error_classifier.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/error_classifier.py), which maps technical errors like HTTP 401 or 429 responses to standardized, actionable user messages via keyword-based pattern matching.**

Open Notebook is an open-source knowledge management platform that integrates multiple AI providers including OpenAI, Anthropic, and Groq. When these external services fail, the application must translate technical provider errors into actionable feedback for end users. The repository implements a robust error classification system that centralizes exception handling across all graph nodes and API layers, ensuring users receive consistent guidance regardless of which underlying provider raised the error.

## The Centralized Error Classification Architecture

The error classification system isolates provider-specific error vocabularies behind a single utility function. Located at [`open_notebook/utils/error_classifier.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/error_classifier.py), the `classify_error` function serves as the sole translation layer between raw provider exceptions and the application's public error types defined in [`open_notebook/exceptions.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/exceptions.py).

Every graph node that invokes language models—such as those in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) and [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py)—wraps provider calls in `try/except` blocks. When exceptions bubble up from the underlying SDKs, they are immediately passed to `classify_error` for normalization before propagation to the API layer.

## How the classify_error Function Maps Provider Exceptions

The `classify_error` function implements a deterministic keyword matching algorithm to categorize errors. It constructs a normalized search string by combining the exception type name and message:

```python
combined = f"{error_type_name}: {error_str}"

```

This combined string is then evaluated against the `_CLASSIFICATION_RULES` table. Each rule is a tuple containing:

- A list of **keywords** (e.g., `"authentication"`, `"401"`, `"rate limit"`)
- The **target exception class** from [`open_notebook/exceptions.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/exceptions.py)
- An optional **user-friendly message** (or `None` to forward the original text)

The function returns the first matching rule's exception class and prepared message.

### The Classification Rules Table

The `_CLASSIFICATION_RULES` table in [`error_classifier.py`](https://github.com/lfnovo/open-notebook/blob/main/error_classifier.py) defines specific mappings for common failure modes:

- **Authentication failures**: Keywords like `"authentication"`, `"401"`, or `"invalid api key"` map to `AuthenticationError` with the message *"Authentication failed. Please check your API key in Settings → Credentials."*
- **Rate limiting**: Keywords like `"rate limit"`, `"429"`, or `"too many requests"` map to `RateLimitError` with the message *"Rate limit exceeded. Please wait a moment and try again."*
- **Payload size violations**: Keywords like `"payload too large"` or `"413"` map to `ExternalServiceError` with the message *"The request payload is too large for the AI provider. Try reducing the content size or using a different model."*
- **Network connectivity**: Keywords like `"connecterror"`, `"timeout"`, or `"connection refused"` map to `NetworkError` with the message *"Could not connect to the AI provider. Please check your network connection and provider URL."*

## Implementation in Graph Nodes

Graph nodes implement the error classification system by catching raw provider exceptions and re-raising them as standardized `OpenNotebookError` subclasses. This pattern appears consistently across the codebase:

```python
from open_notebook.utils.error_classifier import classify_error
from open_notebook.exceptions import OpenNotebookError

try:
    response = await provider.chat(messages)
except Exception as e:
    # Convert raw provider error → classified error + user message

    error_cls, user_msg = classify_error(e)
    # Raise the mapped OpenNotebookError so the API layer can handle it uniformly

    raise error_cls(user_msg) from e

```

This approach ensures that the API layer receives only standardized exception types, keeping internal provider details hidden from the UI.

### Unit Test Validation

The classification logic is validated in the test suite. For example, testing HTTP 413 handling:

```python
from open_notebook.utils.error_classifier import classify_error
from open_notebook.exceptions import ExternalServiceError

exc = Exception("HTTP 413: Payload Too Large")
cls, msg = classify_error(exc)

assert cls is ExternalServiceError
assert "payload is too large" in msg.lower()

```

## Fallback Handling and Logging

When `classify_error` encounters an unrecognized exception that matches no rules in the table, it implements a defensive fallback strategy. The function logs a warning containing the original error details and returns `ExternalServiceError` with a truncated version of the original message. This ensures that even novel provider errors surface to users as generic external service failures rather than exposing internal stack traces.

The API routers then catch these classified exceptions and return appropriate HTTP error responses containing only the user-friendly text, maintaining security by hiding internal implementation details.

## Summary

- **Centralized classification**: The `classify_error` function in [`open_notebook/utils/error_classifier.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/error_classifier.py) provides a single point of translation for all LLM provider exceptions.
- **Keyword-based mapping**: The system uses a `_CLASSIFICATION_RULES` table to match error type names and messages against known patterns, returning appropriate `OpenNotebookError` subclasses.
- **Consistent user experience**: Graph nodes in [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) and similar files wrap provider calls to ensure users receive actionable messages like "Authentication failed" or "Rate limit exceeded" instead of raw HTTP status codes.
- **Defensive fallbacks**: Unmatched errors default to `ExternalServiceError` with truncated messages, preventing data leakage while maintaining system stability.

## Frequently Asked Questions

### How does Open Notebook handle unrecognized LLM provider errors?

When the `classify_error` function encounters an exception that matches no keywords in the `_CLASSIFICATION_RULES` table, it logs a warning with the original error details and falls back to `ExternalServiceError` with a truncated message. This ensures users receive a generic "External service error" message rather than internal technical details, while developers can still diagnose issues through application logs.

### Where is the error classification logic implemented in the Open Notebook codebase?

The core classification logic resides in [`open_notebook/utils/error_classifier.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/error_classifier.py), specifically within the `classify_error` function. The public exception hierarchy is defined in [`open_notebook/exceptions.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/exceptions.py), including classes like `AuthenticationError`, `RateLimitError`, and `NetworkError`. Graph implementations that utilize this system are located in files like [`open_notebook/graphs/chat.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/chat.py) and [`open_notebook/graphs/ask.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/graphs/ask.py).

### Can I customize the user-friendly error messages in Open Notebook?

Yes, the user-friendly messages are defined as strings in the `_CLASSIFICATION_RULES` tuples within [`error_classifier.py`](https://github.com/lfnovo/open-notebook/blob/main/error_classifier.py). Each rule contains an optional message parameter that overrides the original provider error text. Modifying these strings will change the feedback presented to users throughout the application, while the exception class mapping ensures API responses remain consistent.

### What types of LLM provider errors does the classification system recognize?

The system recognizes specific patterns for authentication failures (401, invalid keys), rate limiting (429, too many requests), payload size violations (413), network connectivity issues (timeouts, connection refused), and model availability errors. Each category maps to a specific exception class in [`open_notebook/exceptions.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/exceptions.py), enabling the API layer to return appropriate HTTP status codes and user guidance.