protean eventstore dlq
The protean eventstore dlq command group shows the event store's
dead-letter queue: the positions a subscription retried up to max_retries
and then gave up on. Those give-ups are recorded as Exhausted records in
each subscription's internal failed-* stream. list enumerates the
exhausted positions per subscription; inspect re-reads the failing event so
you can see what could not be processed.
This is different from protean dlq. protean dlq manages the
broker dead-letter queue (messages a broker subscription failed and moved
to {stream_category}:dlq). protean eventstore dlq covers event-store
subscriptions (event handlers, command handlers, projectors), which do not use
a broker DLQ; they track failed positions and, on exhaustion, leave the event
in place in the store.
All commands accept a --domain option for the domain module path (defaults to
the current directory) and a --json flag for the shared CLI result envelope.
Commands
| Command | Description |
|---|---|
protean eventstore dlq list |
List exhausted positions, grouped by subscription |
protean eventstore dlq inspect |
Re-read the failing event behind an exhausted position |
protean eventstore dlq list
Lists the exhausted positions across all event-store subscriptions, or a single one filtered by stream category.
# All subscriptions
protean eventstore dlq list --domain=my_domain
# One subscription (by stream category)
protean eventstore dlq list --subscription=order --domain=my_domain
# Machine-readable JSON
protean eventstore dlq list --domain=my_domain --json
Options
| Option | Description | Default |
|---|---|---|
--domain |
Domain module path | . (current directory) |
--subscription |
Filter by stream category (e.g. order) |
All subscriptions |
--json |
Output the result envelope instead of a table | False |
Output
Exhausted positions — my_domain
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Handler ┃ Stream Category ┃ Exhausted Positions ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ app.handlers.OrderHandler │ order │ 42, 87 │
└───────────────────────────────┴─────────────────┴─────────────────────┘
2 exhausted position(s) across 1 subscription(s).
A subscription with no exhausted positions is not shown. When nothing is
exhausted anywhere, the command prints No exhausted positions. and exits 0.
Under --json the result is the shared result envelope, with the
per-subscription list under data.subscriptions:
{
"version": "0.1.0",
"status": "pass",
"data": {
"subscriptions": [
{
"handler": "app.handlers.OrderHandler",
"stream_category": "order",
"exhausted": [42, 87]
}
]
},
"diagnostics": []
}
protean eventstore dlq inspect
Re-reads the event behind an exhausted position and prints its type, global position, and data. The event is read live from the store (it is never copied into the exhausted record), so you always see its current form.
protean eventstore dlq inspect 42 --domain=my_domain
# Machine-readable JSON
protean eventstore dlq inspect 42 --domain=my_domain --json
Options
| Option | Description | Default |
|---|---|---|
POSITION |
Exhausted global position (positional argument) | Required |
--domain |
Domain module path | . (current directory) |
--subscription |
Stream category to search in | All subscriptions |
--json |
Output the result envelope instead of text | False |
Under --json the envelope's data carries position, type,
global_position, and data:
{
"version": "0.1.0",
"status": "pass",
"data": {
"position": 42,
"type": "MyDomain.OrderPlaced.v1",
"global_position": 42,
"data": { "order_id": "abc", "total": 100 }
},
"diagnostics": []
}
Exit codes
| Code | Meaning |
|---|---|
0 |
Success (including "no exhausted positions"). |
1 |
Human mode (--json not set): the domain failed to load. Typer aborts, the same as every other protean command. |
2 |
Usage or environment error: unknown --subscription, unknown position, or an event that can no longer be re-read. Under --json, a domain that failed to load also exits 2 and emits the error envelope. |
Error handling
| Condition | Behavior |
|---|---|
| Invalid domain path | Human mode: "Error loading Protean domain", Typer aborts with exit 1. Under --json: error envelope, exit 2. |
--subscription matches no event-store subscription |
"No event-store subscription found for stream category ...", exit 2 |
inspect position is not exhausted |
"No exhausted position ... found", exit 2 |
inspect event can no longer be read |
"Could not re-read the event ...", exit 2 |
How positions get exhausted
When an event-store handler raises, the subscription records the failed
position and retries it on each recovery pass. After max_retries retries it
writes an Exhausted record and stops retrying. The record carries the failing
event's stream_name and stream_position so inspect can locate the event;
records written before this was added fall back to the origin stream, read by
global position.
For the full error-handling guide, see Error Handling. For subscription lifecycle details, see Subscriptions.
Domain discovery
The protean eventstore dlq commands use the same domain discovery mechanism
as other CLI commands. See Domain Discovery for the
full resolution logic.