Summary
When a queued request fails permanently and lands in the DLQ, the failure reason string
(request.data._lastError, set by queue.ts's fail()) is surfaced in the TUI via /dlq — buried
inside a YAML dump next to the document's original content, but present and readable. The web
client's QueuePanel component has no equivalent at all.
web/src/components/Queue/QueuePanel.tsx's QueueItem (~lines 250-272) renders
persona/model/next_step/attempts/a DLQ badge and never reads item.data or any error field. This
is true for every DLQ'd item today, not specific to any one failure type — a web user sees "this is
stuck in the DLQ" with zero clue why.
Why it matters
Web is the primary surface for non-technical users. A DLQ'd item with no visible reason is a dead
end: nothing tells the user what to fix or whether to retry.
Acceptance (not yet designed — this issue tracks the finding, not a committed shape)
At minimum: a DLQ'd item's failure reason is visible somewhere in the web QueuePanel, in a form a
non-technical user can read (not a raw YAML/JSON dump — that's the TUI's audience, not necessarily
web's). Exact presentation (full detail vs. a short summary line) is an open design question for
whoever picks this up.
Provenance
Found 2026-08-07 during release prep, while verifying that a DLQ-reason requirement landing
elsewhere in the codebase actually reaches both clients. Cross-client parity gap, not caused by any
single change.
Summary
When a queued request fails permanently and lands in the DLQ, the failure reason string
(
request.data._lastError, set byqueue.ts'sfail()) is surfaced in the TUI via/dlq— buriedinside a YAML dump next to the document's original content, but present and readable. The web
client's
QueuePanelcomponent has no equivalent at all.web/src/components/Queue/QueuePanel.tsx'sQueueItem(~lines 250-272) renderspersona/model/
next_step/attempts/a DLQ badge and never readsitem.dataor any error field. Thisis true for every DLQ'd item today, not specific to any one failure type — a web user sees "this is
stuck in the DLQ" with zero clue why.
Why it matters
Web is the primary surface for non-technical users. A DLQ'd item with no visible reason is a dead
end: nothing tells the user what to fix or whether to retry.
Acceptance (not yet designed — this issue tracks the finding, not a committed shape)
At minimum: a DLQ'd item's failure reason is visible somewhere in the web
QueuePanel, in a form anon-technical user can read (not a raw YAML/JSON dump — that's the TUI's audience, not necessarily
web's). Exact presentation (full detail vs. a short summary line) is an open design question for
whoever picks this up.
Provenance
Found 2026-08-07 during release prep, while verifying that a DLQ-reason requirement landing
elsewhere in the codebase actually reaches both clients. Cross-client parity gap, not caused by any
single change.