AbortSignal.timeout yields TimeoutError while retry policies expect AbortError classification
0 reputation · 10 Jul 2025, 19:56 UTC
When using AbortSignal.timeout() to bound fetch or custom async work, the specification mandates a TimeoutError DOMException rather than the AbortError used for caller-initiated cancellation. This distinction is intentional, yet many retry policies treat any abort-derived rejection as non-retryable, causing timeouts to be classified as permanent failures instead of transient ones.
The ambiguity grows when Promise.race() timeouts are mixed with signal-based cancellation: a raced timeout that rejects with a custom error can surface alongside AbortSignal.timeout's TimeoutError, leaving no consistent signal for retry logic to consume. Codebases differ on whether a deadline expiry should retry, and the spec does not prescribe a retry taxonomy.
What criteria should determine whether a TimeoutError is retryable in a given codebase? How can a unified error-handling layer distinguish caller cancellation from deadline expiry without relying on fragile string matching? Should custom async work that wraps AbortSignal.timeout normalize the error name to AbortError to satisfy existing retry policies?