DLQ Reference: Reasons, Entry Shape, Methods
- Docs
- Dead Letter Queue
- Reference
guide · dead letter queue
Every reason, every field.
What each failure reason means, what an entry actually contains once it is written, and the full list of DLQ methods with their embedded and TCP behaviour.
Reference
Section titled “Reference”Why jobs end up in the DLQ
Section titled “Why jobs end up in the DLQ”| Reason | Description |
|---|---|
explicit_fail | A retryable processor failure in the attempt history |
max_attempts_exceeded | A normal processor failure exhausted the job’s attempts |
timeout | A processing timeout; retained on retry attempts and terminal timeout entries |
stalled | Job stopped sending heartbeats (worker likely crashed) |
ttl_expired | Reserved category; current waiting-job TTL expiry removes the job instead of creating a DLQ entry |
worker_lost | Reserved category; current disconnect/lock recovery is classified as stalled |
unknown | Fallback for unclassified failures |
The entry’s reason is the terminal cause. Its attempts array preserves the
cause of every failed attempt, so a timeout followed by a normal processor
failure is represented as [timeout, max_attempts_exceeded], while two
consecutive timeouts remain [timeout, timeout].
Entry structure
Section titled “Entry structure”interface DlqEntry<T> { job: Job<T>; // The failed job enteredAt: number; // When first moved to DLQ reason: FailureReason; // Why it failed error: string | null; // Error message attempts: AttemptRecord[]; // Full attempt history retryCount: number; // Times retried from DLQ lastRetryAt: number | null; // Last DLQ retry time nextRetryAt: number | null; // Next scheduled auto-retry expiresAt: number | null; // When entry expires}Each AttemptRecord carries the attempt number, start and failure timestamps, failure reason, error message, and duration in ms.
Bun Queue methods
Section titled “Bun Queue methods”| Method | Result | Runtime behavior |
|---|---|---|
getDlq(filter?) | DlqEntry[] | Synchronous embedded snapshot |
getDlqAsync(filter?) | Promise<DlqEntry[]> | Authoritative embedded or TCP read |
getDlqStatsAsync() | Promise<DlqStats> | Authoritative embedded or TCP statistics |
retryDlqAsync(id?) | Promise<number> | Re-queues selected entries and returns the count |
retryDlqByFilterAsync(filter) | Promise<number> | Re-queues matching entries |
removeDlqJob(id) | Promise<boolean> | Permanently removes one job; rejects broker errors |
removeDlqJobAsync(id) | Promise<boolean> | Explicit alias of removeDlqJob |
purgeDlqAsync() | Promise<number> | Permanently removes every entry and returns the count |
Selective removal is idempotent: false means the entry did not exist. It is
not an error fallback. A failed durable delete rejects and leaves the DLQ entry
authoritative.
Where to go next
Section titled “Where to go next”| DLQ Operations from the Queue Object | The same operations from an existing Queue instance |
| Dead Letter Queue | What the DLQ is, and a first look at what failed |
| DLQ Operations | Filter, retry selectively, check health, purge |
| Automatic DLQ Retry with Backoff | Let bunqueue re-queue dead entries on a backoff |
| DLQ Configuration | autoRetry, maxAge, maxEntries and the defaults |