Error Classification
Sparrow classifies every delivery error into categories. The classification determines whether the delivery is retried or permanently failed.
Error Categories
Section titled “Error Categories”| Category | Retryable | Description |
|---|---|---|
success | n/a | Delivery succeeded |
client_error | No | HTTP 4xx response (bad request, unauthorized, not found, etc.) |
server_error | Yes | HTTP 5xx response (internal server error, bad gateway, etc.) |
timeout | Yes | Request timed out before receiving a response |
connection_refused | Yes | Target endpoint refused the TCP connection |
network_error | Yes | Other network errors (ECONNRESET, EPIPE, EHOSTUNREACH) |
dns_error | No | DNS resolution failed (no such host) |
tls_error | No | TLS/SSL handshake failure (certificate errors) |
rate_limited | Yes | HTTP 429 response. Retried after Retry-After delay (doesn’t count as attempt) |
unexpected_status | No | HTTP 2xx/3xx response that did not match expected_status_codes |
template_error | No | The subscription’s transform failed to render, so nothing was sent (on_transform_error: fail). Retryable by hand after fixing the template. Never counts toward webhook health. See When a template fails. |
unknown | No | Unclassified error |
Retry Behavior
Section titled “Retry Behavior”When a delivery attempt fails with a retryable error category, Sparrow re-enqueues the delivery with exponential backoff:
backoff = retry_backoff_seconds * 2^(attempt - 1) # capped at 24 hoursRetries continue until:
- The delivery succeeds
max_retriesattempts are exhausted (terminalFAILEDstatus)- The event’s
ttl_secondsexpires (terminalEXPIREDstatus)
Non-retryable errors immediately mark the delivery as FAILED regardless of remaining retry budget.
A delivery with status paused was created while its subscription was paused.
It has no error category, is never attempted until retried, and does not
affect health. See Pausing a Subscription.
Classification Logic
Section titled “Classification Logic”The error classifier inspects the Go error chain to determine the category:
-
HTTP response code — If a response was received:
- 2xx matching
expected_status_codes->success - 4xx ->
client_error - 5xx ->
server_error
- 2xx matching
-
Error type inspection — If no response:
*net.DNSError->dns_error- TLS-related errors ->
tls_error net.ErrorwithTimeout()->timeoutsyscall.ECONNREFUSED->connection_refusedsyscall.ECONNRESET,EPIPE,EHOSTUNREACH->network_error- String pattern fallback for edge cases
Monitoring Errors
Section titled “Monitoring Errors”Use the health endpoints to monitor error patterns:
GET /v1/consumers/{consumer}/webhooks/{webhook_id}/healthreturns error category breakdown (client_errors, server_errors, timeout_errors, network_errors) for the last 24 hoursGET /v1/webhooks(filtered by health) finds all webhooks withUNHEALTHYorDEGRADEDstatusGET /v1/consumers/{consumer}/deliveries/{delivery_id}/attemptsshows per-attempt error details for debugging