> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comforthub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Redrive a dead letter

> Put a failed message back on the queue once the cause is fixed

export const Touches = ({systems}) => <p>
    <strong>Systems involved:</strong>{" "}
    {systems.split(",").map((s, i) => <span key={s}>
        {i > 0 ? " · " : ""}
        <a href={"/systems/" + s.trim()}>{s.trim().replace(/-/g, " ")}</a>
      </span>)}
  </p>;

<Touches systems="supabase-backend, sentry" />

A message that fails all its retries, or that the engine refuses in a way a retry could never change, is moved to the queue's dead-letter box. The monitor sees it there and opens a condition, so the Sentry issue is what tells you. Nothing is lost: the message is a pointer to a record, and once the cause is fixed it can be put back on the queue and run again, from the record's current state.

## Before you start

* The Sentry issue. Its title is the action's name followed by **is blocked before business completion**; it is urgent or for review by the action's weight. Under **Additional Data**, the evidence names the queue, the message number and the operation id.
* The cause fixed. A redrive with the cause still there just dies again.

## Steps

<Steps>
  <Step title="Find the cause">
    The issue's evidence locates the message; Sentry also holds a separate issue for the failure itself, tagged as a dead letter, with the reason in plain words. Fix that first: add the missing catalog item, correct the record, ship the code fix.
  </Step>

  <Step title="Run the redrive">
    In the engine's GitHub repository, open **Actions** and run the **redrive** workflow with:

    * **mode**: **write**. The other choice, **list**, only prints what is in the boxes and moves nothing.
    * **queue**: the dead-letter box to search. Type the box the issue's evidence names; the three box names are on [Names](/reference/names). Leave it blank to search every box.
    * the **message number** field: the message number from the evidence.
    * the **max** field: how many messages the run may move. It defaults to one and the run refuses if more would move.

    The workflow moves the message back onto the queue it came from, keeping its operation id, and records that it did. The worker picks it up within a minute.
  </Step>

  <Step title="Check the record">
    Look at the record the message pointed to. The outcome the message was meant to produce is now there.
  </Step>

  <Step title="Clear any twins">
    If the same record died more than once (two triggers, two messages), redrive one and delete the others; the second run would only repeat the first.
  </Step>
</Steps>

## How you know it worked

* The work check runs every minute. On its next run the dead letter is gone from the box and the operation has completed, so the condition recovers and the monitor resolves the Sentry issue itself.
* If the message dies again, the condition stays open and a fresh dead-letter issue tells you why.

## Why some letters arrive at once

Two kinds of failure reach the box, and the dead-letter issue says which.

* **A refusal the engine will repeat.** A value missing that the record needs, a value this side cannot read, a record colliding with one that already exists. Retrying would only get the same answer, so the message dies on its first delivery.
* **Trouble that passes.** Zoho or QuickBooks down or refusing to talk, the database briefly unreachable. The message is retried on a widening schedule, up to ten deliveries, and only then dies.

## Related

* [How the monitor works](/handbook/running/how-the-monitor-works)
* [Act on a Sentry email](/handbook/running/act-on-a-sentry-email)
