Errors
The full vocabulary of the codes, and which ones are worth retrying.
Every failure has an HTTP status and a stable code. The status says whose problem it is,
the code says which one, and together they say whether retrying makes any sense.
| Status | code |
What happened | Retry |
|---|---|---|---|
| 429 | RATE_LIMITED |
over 60 sends a minute per key | yes, after Retry-After |
| 502 | SMTP_DELIVERY_FAILED |
the SMTP server does not answer or rejects temporarily | yes |
| 503 | none, HTML body | pigeon unreachable, almost always a deploy | yes |
| 504 | none | the proxy closed the wait | yes |
| 502 | SMTP_DELIVERY_REJECTED |
the SMTP server rejected it for good | no |
| 409 | IDEMPOTENCY_IN_PROGRESS |
a send with the same Idempotency-Key is still running |
yes, in a few seconds |
| 409 | SMTP_AUTH_FAILED |
the SMTP credentials of the project were rejected | no |
| 409 | SMTP_NOT_CONFIGURED, SMTP_INCOMPLETE, SMTP_CREDENTIALS_MISSING |
the project is not configured to send | no |
| 400 | VALIDATION_ERROR, INVALID_JSON, PROJECT_ID_MISMATCH |
the request is wrong | no |
| 401 | INVALID_API_KEY, UNAUTHENTICATED |
key missing, revoked or invalid | no |
| 403 | FORBIDDEN_ORIGIN |
the call comes from a browser | no |
| 404 | TEMPLATE_NOT_FOUND, PROJECT_NOT_FOUND |
the template does not exist or is not yours | no |
| 413 | FILE_TOO_LARGE |
attachments over the limit | no |
| 415 | UNSUPPORTED_MEDIA_TYPE |
unexpected Content-Type |
no |
| 500 | INTERNAL_ERROR |
a failure of pigeon | no |
The two 502s are not the same thing
SMTP_DELIVERY_FAILED is the mail server unreachable, a timeout, or a temporary rejection of
the protocol (the SMTP 4xx: greylisting, mailbox full for the moment, service unavailable).
The same email, sent a few seconds later, may go out.
SMTP_DELIVERY_REJECTED is a final rejection (the SMTP 5xx: recipient does not exist,
message refused). Retrying it only produces more failed rows, and what needs fixing is the
address or the content.
A 500 is not retried because it is a failure of pigeon: if it comes back, it comes back the
same. A 503 is, and it is by far the most frequent case, because it is the window in which
the container is replaced by a deploy.
IDEMPOTENCY_IN_PROGRESS is the only 409 worth retrying: it says that another attempt with
your own key is talking to the mail server right now, and the outcome is not known yet. The
other 409s are configuration to fix.
The id survives the failure
On a delivery failure, details.emailId carries the id of the row that was recorded. It is
what lets you find the attempt again in the panel, and it is worth saving next to your own
record: it turns a report into something verifiable instead of a guess.