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

# Trace a Workflow to Find and Fix Bugs

> Follow an execution path across services and queues to find where it actually breaks, then land a scoped fix once the cause is confirmed.

**Scenario:** A user reports they never got notified when their build finished. You didn't write the notification pipeline, and it spans an event emitter, a queue, a consumer, and two delivery channels. Grepping for "notification" turns up a dozen files — before you can fix anything, you need to know which of them are actually on this path, and in what order.

***

<div class="dotted-steps">
  <Steps>
    <Step title="Make revolte map the flow" icon="terminal">
      Open a session in the repo and describe the trigger the same way you'd describe it to a teammate — no file names required.

      ```text theme={"dark"}
      Trace how a notification reaches a user, starting from the event
      that triggers it (a build completing) through to delivery. List
      every file and function on the path, in order.
      ```

      ```text theme={"dark"}
      1. jobs/buildRunner.ts             → emits `build.completed`
      2. events/emitter.ts               → publishes to the `notifications` queue
      3. workers/notificationConsumer.ts → handleBuildCompleted() builds the payload
      4. delivery/dispatch.ts            → dispatch() fans out to websocket + push
      5. client/NotificationCenter.tsx   → renders on `notification:new`
      ```

      Five hops, in actual call order. Skim it against what you already know before moving on — the next part builds on this map, so it's worth correcting now if a hop looks off.
    </Step>

    <Step title="Drill into the weak point" icon="search">
      Stay in the same session so you don't have to re-establish context. Pick the hop that looks riskiest — usually wherever two things happen back to back without visible error handling — and narrow in on it one question at a time.

      ```text theme={"dark"}
      Does dispatch() retry either channel if the send fails?
      ```

      > No. Both `websocketChannel.send()` and `pushChannel.send()` are single-attempt, best-effort calls — no retry on either one.

      No retries isn't the whole story on its own — a flaky send on one channel shouldn't matter if the other still fires.

      ```text theme={"dark"}
      If there's no retry, is there at least a fallback — does push
      still fire if the websocket send fails?
      ```

      > Unclear from a static read. Both sends live inside the same `try/catch`, so whether `pushChannel.send()` runs after a websocket failure depends on exactly where execution goes when the throw happens.

      ```text theme={"dark"}
      Walk through what happens step by step when websocketChannel.send()
      throws inside that try/catch — does execution ever reach the
      pushChannel.send() line?
      ```

      > No — the throw jumps straight to the catch block, which only logs at debug level. `pushChannel.send()` is never reached. One flaky channel silently kills the other.

      That's the kind of failure a text search doesn't surface — it takes following the event through the queue and reading how the error is actually handled.
    </Step>

    <Step title="Turn it into a fix" icon="wrench">
      The failure mode is confirmed, so ask for the fix directly.

      ```text theme={"dark"}
      Fix dispatch() so a failure in one channel can't block the other,
      and add a regression test.
      ```

      > * Each channel send gets its own `try/catch`.
      > * Failures log at `warn` with the channel name and notification id.
      > * New test: push still fires when the websocket send throws.

      Review the diff and run the new test locally before opening a PR, same as with any change — tracing the flow gets you to that point faster, it doesn't replace it.
    </Step>
  </Steps>
</div>

***

## Why this matters

Async boundaries — queues, consumers, fan-out — are exactly where a human loses the thread scanning files by hand. Tracing the actual execution path, including how errors are swallowed, turns "user says they didn't get notified" into a specific line of code and a fix, in one pass.

## Related

* [Investigate and Fix a Production Bug](/use-cases/fix-a-bug)
* [Application Logs](/deployments/observability/application-logs)
