fix: map 401 and 403 validation_error to ValidationError

M4
13h ago
+25-2

The error docs return validation_error with 400, 401 and 403.
401 is "API key is invalid" on sending endpoints, and 403 covers "The domain.com domain is not verified" and
the testing-mode recipient restriction. ERRORS only has validation_error under 400 and 422, so the 401 and 403
responses come back as a plain ResendError with an empty suggested_action, and except resend.ValidationError
doesn't catch them. An unverified sending domain is probably the most common setup mistake, so it's a shame
it's the one that slips through.

This adds validation_error to the 401 and 403 entries, plus two tests next to the existing 400 and 422 ones.
It's backward compatible because ValidationError subclasses ResendError, and code, message, error_type
and headers stay the same.

I noticed this while writing the error handling for moving Ventute (which sends all its email through Resend)
from raw httpx calls to the SDK.

One thing I left alone on purpose. The docs no longer list invalid_api_key, which is the only name
InvalidApiKeyError is registered under, so I don't think that class gets raised anymore. Whether an invalid key
should raise InvalidApiKeyError instead of ValidationError felt like your call, so this PR just follows the
same name, same class rule. Happy to change it if you'd prefer the other way.

Testing

Both new tests fail on main and pass here. The full suite passes on Python 3.14 and 3.8 (853 tests), and flake8
and mypy show nothing new.


Summary by cubic

Maps validation_error responses from 401 (invalid API key on sending endpoints) and 403 (unverified domain, testing-mode recipient restriction) to ValidationError so they carry a suggested_action and can be caught with except resend.ValidationError instead of falling back to a plain ResendError.

  • Backward compatible: ValidationError subclasses ResendError, and code, message, error_type, and headers stay the same.
  • invalid_api_key is left untouched; the Resend error docs only list validation_error for 401/403, so InvalidApiKeyError may no longer be raised.