Silent failure in your core action

Every product has one action that matters more than the rest: checkout, publish, send, or deploy. When it fails loudly, you hear about it. When it fails quietly, nobody sees an error and nobody files a ticket. This scout watches your most important flow and catches the failures nobody reports.

What the scout looks at

The scout looks for patterns like Fig. 1: you deployed at 14:02. People are still trying to publish, but fewer are finishing. No error page rendered and no alert fired. If both lines had dropped, that's a traffic change – not a break.

14:02 deploy

~1,240/day vanish here – no error, no alert

Started publishing · ~4,000/dayFinished · 92% → 61%

Fig. 1What the scout saw: Your deploy went out at 14:02. The orange gap is everyone who started and never finished.

The report in your inbox

When your product emits signals that indicate your core action is failing, a scout opens a report. Fig. 2 breaks the card down part by part. Click Review and the report opens Fig. 3 with the full evidence, the raw signals, and options to take action. Yours would look like this one, but name your events, your deploys, and your users.

P1Publish completion rate down 31 points while attempts hold steady Completion rate fell 92% → 61% after the 14:02 deploy while attempts held steady – a handled timeout, retried silentlyScout · core action funnelReadyActionable2h ago
ArchiveReview
Fig. 2Once surfaced, your inbox surfaces this report card. The card includes its claim and triage, with the evidence sitting inside the report itself.Hover over the figure to learn about each element.
P1Publish completion rate down 31 points while attempts hold steady ReadyActionableScout · core action funnel· 2h ago
ArchiveCreate PR
Summary

Since the 14:02 deploy, publish attempts are flat at ~4,000/day but the completion rate fell from 92% to 61%. The drop is uniform across source, device, and geo, so it isn't a traffic-mix change, and the publish_completed event is still firing normally elsewhere.

Error Tracking shows a new handled timeout on the publish path, caught by the retry wrapper and never rethrown – so no error page rendered and no alert fired. Session Replay matches: users click Publish, watch the spinner, and leave after ~8 seconds.

~1,240 publishes/day failing silently

Suggested fix: Surface the failure to the user instead of retrying silently. The timeout itself is the root cause and a separate follow-up – this PR is about making it visible.

Evidence4 sources
Your product eventsHow many people start your core action and how many finish, compared with the last two weeks.
Error TrackingThe failures that show up as errors – including the ones your code catches, so the user never sees them.
Session ReplayThe failures that never become errors – recordings of people who started, got stuck, and gave up.
Your codebaseYour deploys, so a drop can be matched to the change that caused it instead of just a time of day.
Fig. 3The report opened. From here, you can review the evidence and open a pull request.Hover over the figure to learn about each element.

The pull request you merge

When you're ready to open a pull request, the agent does it for you, attaching the evidence along the way. You review and merge it like any other – nothing merges without you.

Reports are free. Pull requests are $15 each, with your first three a month free. See self-driving Pricing.

The scout itself

Scouts are the heart of the self-driving system – they're instructions an agent follows on a schedule – Fig. 4 is the actual file for this guide's custom scout.

signals-scout-silent-failure/SKILL.md
---
name: signals-scout-silent-failure
description: >
Watches the completion rate of one named core action for breaks from its own norm, and
reports the likely cause – with swallowed exceptions as the first thing it looks for.
allowed_tools:
- emit_report
- edit_report
---
# Silent failure in the core action
Watch one named flow for failures that never surface as errors.
The mechanism this is built around: **something caught the failure.** A retry wrapper, a
`try`/`catch` with a log line, a fallback that returns an empty result. The user sees a spinner
and then nothing, no error page renders, no alert fires, and the only trace is the completion
rate quietly dropping. That's what makes it silent, and it's what this scout looks for first.
Narrower than `signals-scout-anomaly-detection`, which builds a durable watchlist of the
insights a team actually looks at and scores each one against a seasonality-matched baseline.
This one watches a single flow you name, every run, whether or not anyone has built an insight
for it. If the core action is already on that scout's watchlist and you're hearing about breaks
in time, you don't need both.
Daily is the fleet default. For a flow where hours matter, set `run_interval_minutes` to 60 when
you create the scout – the tradeoff is that hourly buckets are noisier, so raise the volume
floor below to match.
## Discriminator
Emit a report when the **completion rate** – completions divided by attempts – breaks from its
trailing two-week norm for the same day of week. Write nothing when attempts and completions
moved together and the rate held: that's a traffic change, not breakage.
Attempts are the disqualifier check, not half the trigger. Watching two counts separately leaves
you stuck the moment both move a little; watching the rate doesn't.
### The bar
A starting point, to be tuned against what this flow's data actually does:
- a completion rate **≥10 points below** its trailing 14-day median for the same weekday, on a
complete bucket, and
- **≥500 attempts** in that bucket.
The volume floor matters more than the threshold. A completion rate computed on 40 attempts is
noise, and a scout that fires on it is exactly the crying-wolf failure the discriminator is
meant to prevent. If the flow doesn't clear the floor, widen the bucket rather than lowering the
bar, and write what you chose to the scratchpad.
## Explore
1. **Confirm the instrumentation still works.** Before anything else: is the completion event
still firing at all, and was it renamed, moved, or removed in the deploy window? A broken
tracking call looks identical to a broken product – attempts flat, completions gone – and it
is the most likely false positive for this scout. Check the event's total volume across all
properties, not just within the flow. `signals-scout-observability-gaps` watches this kind of
drift more broadly.
2. **Check whether the drop is uniform.** Did the completion rate fall across every segment, or
only inside a new or shifted one? Steady attempts with a falling rate is also the shape of a
traffic-composition change – a campaign bringing lower-intent users, a new geo, a bot wave.
Nothing is broken in that case, and the rate framing alone won't catch it. Break down by
source, device, geo, and new-vs-returning before going further.
3. **Find what was caught.** Look for new or spiking error-tracking issues on the same code
path, weighting **handled** exceptions – the ones that never reached the user. A caught
timeout, a retry that exhausted, a fallback that returned empty. This is the mechanism the
whole scout is built around, so look here before looking anywhere else.
4. **Check the failures that never reached your server.** If Error Tracking is clean, the failure
may not have made it out of the browser: a dropped request, an ad blocker or CSP rule
blocking the call, the tab closing mid-request. Session Replay is the only thing that sees
these – look for stalls, rage clicks, and abandonment at a consistent point in the flow.
5. **Locate it in the flow.** If intermediate events exist, find the step where the drop happens.
Without them you can say the flow broke, but not where.
6. **Tie it to a deploy.** Where a deploy sits in the window, include the commit range.
7. Name the most likely cause in the report. A rate that moved with no cause attached is
something the reader still has to go investigate themselves.
## Disqualifiers
- Attempts and completions moved together – the rate held.
- The completion event stopped firing entirely, or was renamed in the window. That's an
instrumentation finding, not a product one, and it should say so.
- The rate fell only inside one new or shifted segment – that's a mix change, not breakage.
- The bucket is below the volume floor.
- The change is within normal weekday/weekend variance.
- A known, announced maintenance window covers the period.
Fig. 4The scout itself – the file an agent follows on a schedule.

It reads more than one signal source, so the report can name a likely cause, not just a number that moved.

  • Your product events

    How many people start your core action and how many finish, compared with the last two weeks.

  • Error Tracking

    The failures that show up as errors – including the ones your code catches, so the user never sees them.

  • Session Replay

    The failures that never become errors – recordings of people who started, got stuck, and gave up.

  • Your codebase

    Your deploys, so a drop can be matched to the change that caused it instead of just a time of day.

The schedule it runs on

This custom scout runs daily by default. You can choose to run it every 30 minutes up to once a day. It only writes when something is wrong, so most days it's silent.

Add this to your scout troop

This is how the scout appears in PostHog once it's running – a scheduled agent that files a report when it finds something.

Preview

  • RequiredA core action with a start and finish event, named explicitly when you add the scout – it can't guess which flow is the whole point of your product
  • RequiredError Tracking instrumented, including the paths where exceptions are caught
  • RecommendedYour codebase connected via GitHub, to correlate a break against deploys
  • RecommendedSession Replay, for failures that never reach your server at all
  • OptionalIntermediate events inside the flow, if you have them – they're what turns "it broke" into "it broke at the payment step"
Add this scoutOpens PostHog with it prefilled. Review it, then hit Create.

Not set up yet? One command installs PostHog, connects GitHub, and turns on a default troop of scouts. That troop doesn't include this one – add it above once you're set up.

npx @posthog/wizard self-driving
signals-scout-silent-failureAdd this scout