How Open Notebook's Error Classification System Translates LLM Provider Exceptions to User-Friendly Messages
Open Notebook centralizes LLM error handling through a keyword-based classification system that maps raw provider exceptions to actionable user messages while hiding technical implementation details.
Open Notebook, an open-source AI note-taking application, handles errors from multiple language model providers through a sophisticated error classification system. Instead of exposing raw API errors to users, the system normalizes exceptions from OpenAI, Anthropic, Groq, and other providers into consistent, actionable feedback. This architecture lives in open_notebook/utils/error_classifier.py and integrates deeply with the application's graph-based execution nodes.
How the Error Classification System Works
Exception Capture in Graph Nodes
Every graph node that invokes a language model wraps provider calls in try/except blocks. When an exception bubbles up from operations in open_notebook/graphs/chat.py, open_notebook/graphs/ask.py, or similar transformation pipelines, the raw error is immediately passed to the classify_error utility. This ensures no provider-specific exception reaches the user interface unprocessed.
Keyword-Based Mapping Logic
The classify_error function in open_notebook/utils/error_classifier.py implements a pattern-matching algorithm against the _CLASSIFICATION_RULES table. The function constructs a normalized string combining the exception type name and message (combined = f"{error_type_name}: {error_str}"), then iterates through classification rules. Each rule specifies:
- A list of trigger keywords (e.g.,
"authentication","401","invalid api key") - A target exception class from
open_notebook/exceptions.py(e.g.,AuthenticationError,RateLimitError) - An optional user-friendly message (or
Noneto preserve original text)
The first matching rule wins, returning both the mapped exception class and the prepared message.
Fallback Handling and Logging
When no classification rules match, the system logs a warning and defaults to ExternalServiceError with a truncated version of the original message. This prevents information leakage while ensuring the application degrades gracefully for unknown error types.
The Classification Rules Table
The _CLASSIFICATION_RULES table maps common LLM provider error patterns to specific exception types:
- Authentication errors: Keywords like
"authentication","401", or"invalid api key"map toAuthenticationErrorwith the message "Authentication failed. Please check your API key in Settings → Credentials." - Rate limiting: Keywords including
"rate limit","429", or"too many requests"triggerRateLimitErrorwith "Rate limit exceeded. Please wait a moment and try again." - Payload size violations:
"payload too large"or"413"errors map toExternalServiceErrorwith instructions to reduce content size or switch models. - Network failures:
"connecterror","timeout", or"connection refused"generateNetworkErrormessages prompting users to check network connectivity and provider URLs.
Implementation Examples
Graph nodes implement the classification pattern by wrapping provider calls:
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
Unit tests validate specific mappings, such as HTTP 413 errors:
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()
Propagation to the API Layer
After classification, the router layer catches the mapped exceptions and returns appropriate HTTP responses containing only the user-friendly text. This design decouples provider-specific error vocabularies from the UI, ensuring that whether an OpenAI rate limit or an Anthropic authentication failure occurs, users receive consistent, actionable guidance without exposure to internal API details.
Summary
- Open Notebook uses a centralized error classification system in
open_notebook/utils/error_classifier.pyto normalize LLM provider exceptions. - The
classify_errorfunction matches combined exception type and message strings against keyword rules in_CLASSIFICATION_RULES. - Mapped exceptions include
AuthenticationError,RateLimitError,NetworkError, andExternalServiceErrorwith user-friendly messages. - Graph nodes in files like
open_notebook/graphs/chat.pywrap provider calls to ensure all errors are classified before reaching the API layer. - Unmatched errors fall back to
ExternalServiceErrorwith logging to prevent information leakage while maintaining system stability.
Frequently Asked Questions
How does Open Notebook handle unknown LLM provider errors?
When the error classification system encounters an exception that matches no predefined rules, it logs a warning and defaults to ExternalServiceError with a truncated message. This ensures users receive a generic but safe error notification while developers can investigate the unhandled case through logs.
Where is the error classification logic implemented in the Open Notebook codebase?
The core logic resides in open_notebook/utils/error_classifier.py, specifically within the classify_error function and the _CLASSIFICATION_RULES table. Exception class definitions are located in open_notebook/exceptions.py, while graph implementations in open_notebook/graphs/chat.py and similar files invoke the classifier.
Can the error classification system distinguish between different types of rate limits?
Yes, the system recognizes rate limiting through multiple keyword patterns including "rate limit", "429", and "too many requests", mapping them all to RateLimitError with a consistent user message. This handles variations in how different providers like OpenAI, Anthropic, or Groq report throttling.
Why does Open Notebook use exception chaining when raising classified errors?
The system uses raise error_cls(user_msg) from e to preserve the original exception traceback while replacing the public-facing error. This allows developers to access full provider error details in logs for debugging, while users only see the sanitized, actionable message returned by the API.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →