Repository navigation
SendGrid Errors
SendGrid throws SendGridError for invalid configuration, local request
validation, and vendor responses. sendMail() may also reject with a raw
GuardianError when the request itself fails schema validation before any
network call is made — see Schemas.
import {
SendGridError,
SendGridErrorCodes,
} from '@tundraconnect/sendgrid/errors';
const error = new SendGridError('AUTH_REQUIRED', { status: 401 });
console.log(error.message);
console.log(SendGridErrorCodes.AUTH_REQUIRED);SendGrid does not publish discrete machine-readable error codes — every
4xx/5xx response body is a list of free-text { message, field, help? }
entries (see ErrorSchemaObject). These codes are therefore
connect-specific, keyed off the HTTP status the vendor actually returned.
| Code | Meaning |
|---|---|
CONFIG_INVALID_API_KEY |
auth is missing, isn't type: 'BEARER', or its token is blank or not a string. |
AUTH_REQUIRED |
SendGrid returned 401 Unauthorized. |
VALIDATION_ERROR |
SendGrid returned 400 Bad Request. |
FORBIDDEN |
SendGrid returned 403 Forbidden (plan or key permissions). |
NOT_FOUND |
SendGrid returned 404 Not Found. |
METHOD_NOT_ALLOWED |
SendGrid returned 405 Method Not Allowed. |
PAYLOAD_TOO_LARGE |
SendGrid returned 413 Payload Too Large. |
RATE_LIMITED |
SendGrid returned 429 Too Many Requests. |
RESPONSE_ERROR |
A 200/202 response body failed schema validation. |
SERVICE_UNAVAILABLE |
A 5xx response, or any response whose body didn't parse. |
TIMEOUT |
SendGrid did not answer within the client timeout (timeoutSeconds in context). |
NETWORK_ERROR |
fetch failed before any response (DNS, TLS, connection reset); the transport error is the cause. |
UNKNOWN_ERROR |
An unmapped status was returned, or an unknown code was supplied. |
The resolved code is also available as a public, readonly error.code
property — branch on failure mode without matching against .message:
if (error instanceof SendGridError && error.code === 'NOT_FOUND') {
// ...
}Use getContextValue() to read diagnostic metadata such as vendor,
status, the raw vendor errors array, and id (SendGrid's request id,
when present):
try {
await client.sendMail(request);
} catch (error) {
if (error instanceof SendGridError) {
console.log(error.getContextValue('status'));
console.log(error.getContextValue('errors'));
}
}TIMEOUT, NETWORK_ERROR, SERVICE_UNAVAILABLE and RATE_LIMITED mean
"no answer yet": retrying later can help. Every other code is a definite
refusal or a misconfiguration that retrying will not fix. Branch on the
readonly err.transient, which is true for exactly these four, rather
than listing codes yourself. The set is also exported as
SENDGRID_TRANSIENT_CODES from @tundraconnect/sendgrid/errors.
import { SendGridError } from '@tundraconnect/sendgrid/errors';
declare function callTheClient(): Promise<unknown>;
try {
await callTheClient();
} catch (err) {
if (err instanceof SendGridError && err.transient) {
// queue it and try again later
}
throw err;
}| Context | Present on | Meaning |
|---|---|---|
timeoutSeconds |
TIMEOUT |
The deadline that was missed, in seconds. |
A rate-limited request throws RATE_LIMITED. Two context values tell you what to
do next:
| Context | Meaning |
|---|---|
retryAfterSeconds |
Seconds the vendor asked you to wait, parsed by RESTler from Retry-After (delta seconds or an HTTP-date), X-RateLimit-Reset-After, RateLimit-Reset, or an epoch-seconds X-RateLimit-Reset. undefined when the response carried none — never a guess. |
retried |
Set only when maxRetryWait is configured: true if RESTler already waited once and was throttled again, false if it did not wait (the hint exceeded the cap, or there was no hint to wait on). |
Nothing is retried by default. Opt in with two client options (seconds,
each 0–120):
-
maxRetryWait— when a 429 carries a hint no longer than this, RESTler waits that long and retries once; otherwise it throwsRATE_LIMITEDimmediately.0disables the retry. -
defaultRetryWait— the wait used when a 429 carries no hint. Without it a hintless 429 is never retried: RESTler does not invent a delay. Only consulted whenmaxRetryWaitis set, and still capped by it.
| Code | Raised when |
|---|---|
WEBHOOK_INVALID_HEADERS |
A required signature header is missing. |
WEBHOOK_TIMESTAMP_INVALID |
Unparseable timestamp, or outside the tolerance window. |
WEBHOOK_INVALID_KEY |
The verification key is not a valid P-256 public key. |
WEBHOOK_SIGNATURE_INVALID |
Treat the request as forged. |