Error Handling & Exceptions
Relevant source files
The following files were used as context for generating this wiki page:
Resend-python provides a structured exception hierarchy to handle API errors and client-side validation issues. The system maps HTTP status codes and specific API error types to specialized Python exception classes, allowing you to implement granular error handling.
Exception Hierarchy
All custom exceptions in the library inherit from the base ResendError. This base class captures essential error metadata including the HTTP status code, the error type returned by the API, and the response headers.
Core Exception Classes
| Exception Class | HTTP Code | Description |
|---|---|---|
ResendError | Variable | Base class for all Resend-related errors. |
ValidationError | 400, 422 | Raised when the request payload fails validation. |
MissingApiKeyError | 401 | Raised when the API key is missing or invalid. |
RateLimitError | 429 | Raised when rate limits or quotas are exceeded. |
NoContentError | N/A | Raised when an API response returns no content (e.g., null JSON). |
ApplicationError | 500 | Raised when a server-side error occurs. |
MissingRequiredFieldsError | 422 | Specific type of validation error for missing mandatory parameters. |
Sources: resend/exceptions.py, tests/exceptions_test.py:12-104
Exception Class Diagram
The following diagram illustrates the relationship between the various exception classes within the library.
Error Dispatching Logic
The library uses a dispatch function, raise_for_code_and_type, to instantiate the correct exception based on the API response. This function evaluates both the HTTP status code and the error_type string provided in the JSON body.
Logic Flow
- The HTTP client receives a response.
- If the response is not a success or contains an error body, the client calls
raise_for_code_and_type. - The function checks the
error_typeagainst known mappings (e.g.,rate_limit_exceeded,missing_api_key). - If no specific type matches, it falls back to a code-based mapping (e.g., 422 maps to
ValidationError). - If no mapping exists, a generic
ResendErroris raised.
Specific Error Scenarios
Validation Errors
Validation errors occur during 400 or 422 responses. MissingRequiredFieldsError is a specialized subtype that handles cases where the API explicitly identifies a missing field (e.g., missing_required_field).
Sources: tests/exceptions_test.py:31-48
Rate Limiting
The RateLimitError is raised for three distinct API error types:
rate_limit_exceeded: Too many requests in a short window.daily_quota_exceeded: Daily sending limit reached.monthly_quota_exceeded: Monthly sending limit reached.
Sources: tests/exceptions_test.py:61-82
No Content Errors
The NoContentError is raised by resource modules (e.g., Contacts, Topics, Templates) when the internal mock or API response returns None instead of expected data. This is frequently used to validate response integrity in both sync and async methods.
Sources: tests/contact_topics_test.py:121-124, tests/topics_test.py:46-51, tests/templates_async_test.py:53-61
HTTP Request Failures
The request layer handles failures during the communication phase:
- Decoding Errors: If the API returns non-JSON content (e.g., HTML during a 502 or 429), the library raises a
ResendErrororApplicationErrorwith a message indicating a JSON decoding failure. - Status Preservation: Exceptions preserve the original HTTP headers, such as
retry-afterorx-request-id, allowing developers to inspect rate limit resets or debug requests.
Sources: tests/request_test.py:22-105, tests/request_test.py:202-218
Usage Example
When calling API methods, wrap the execution in a try-except block to handle specific failure modes.
import resend
from resend.exceptions import ValidationError, RateLimitError
try:
resend.Emails.send(params)
except ValidationError as e:
# Handle missing fields or invalid email formats
print(f"Validation failed: {e.message}")
except RateLimitError as e:
# Check headers for retry information
retry_after = e.headers.get("retry-after")
print(f"Rate limited. Retry after {retry_after} seconds.")
Sources: tests/exceptions_test.py:90-104, tests/request_test.py:190-210
Summary
The error handling system ensures that every failed API interaction results in a traceable Python exception. By inheriting from ResendError, the library provides a consistent interface for accessing error codes, messages, and headers across all types of failures, whether they originate from client validation, rate limiting, or server-side issues.