Live demo · no signup

Same report you get after a real run

This is Crash Labs analyzing a sample invoice webhook right now. Scroll the FAIL, blast radius, and retry survival. Then stress your own workflow.

Deploy gate

fail

Not production-ready yet

"Invoice on payment webhook" should not go live yet: 6 critical issue(s) (score 100/100). Biggest risk: "Create Invoice" can fail with no backup path (Create Invoice).

Risk

100/100

Nodes
4
Critical
6
High
5
Outbound
3
Coverage
100%

Coverage 100%. Outbound paths 100% simulated.

How to fix (do these first)

  1. 1.

    "Create Invoice" can fail with no backup path

    Turn on retry for transient SMTP/API errors, and route hard failures to an error branch that alerts someone.

  2. 2.

    "Create Invoice" retries can create duplicates

    Before create/send: check "already processed?" using a unique event/message id. Prefer upserts over creates.

  3. 3.

    Webhook "Payment Webhook" can fire side effects twice

    Store the provider event id; if you've seen it, skip every create/send node.

  • If production retried this 50×, Northwind Ops (simulated) would send 47 copycat emails and create 47 Stripe objects for the same customers.
  • Coverage 100%. Outbound paths 100% simulated.
  • Mock simulation ran 4 steps · 3 external action(s) on happy path.
  • Storyboard sample: Run #1: 1 invoice + 1 email + 1 message · Run #2: 1 invoice + 1 email + 1 message · Run #3: 1 invoice + 1 email + 1 message
  • Retry survival: 3 side effect(s) still fire on delivery #2 (3 idempotency fail · 3 low reversibility).
  • Simulation scenarios: 0/6 passed (N/A counts as pass).
  • Top issue: "Create Invoice" can fail with no backup path @ Create Invoice

Simulation only — not a guarantee of production safety. Crash Labs does not call your live Stripe, Gmail, or other APIs.

Blast radius · Northwind Ops (simulated)

If production retried this 50×, Northwind Ops (simulated) would send 47 copycat emails and create 47 Stripe objects for the same customers.

50 trigger fires into one simulated company. No real APIs. This is what would leave the building.

50

emails out

Emails
50
SMS
0
Invoices
50
Stripe
50
Commerce
0
CRM
0
Files
0
Customers
3

Run storyboard

  1. Run #1: 1 invoice + 1 email + 1 message
  2. Run #2: 1 invoice + 1 email + 1 message
  3. Run #3: 1 invoice + 1 email + 1 message
  4. ···
  5. Run #14: 1 invoice + 1 email + 1 message
  6. ···
  7. Run #25: 1 invoice + 1 email + 1 message
  8. ···
  9. Run #48: 1 invoice + 1 email + 1 message
  10. Run #49: 1 invoice + 1 email + 1 message
  11. Run #50: 1 invoice + 1 email + 1 message

Fake inbox / anomalies

  • critical 50 near-identical chat messages posted.
  • critical 47 identical emails to ada@example.com with subject "Your invoice".
  • critical 47 Stripe stripe:invoice(s) for customer key "ada@example.com".
  • high 2 identical emails to cara@example.com with subject "Your invoice".
  • Your invoice

    to cara@example.com · after run #50

  • Your invoice

    to ada@example.com · after run #49

  • Your invoice

    to ada@example.com · after run #48

  • Your invoice

    to ada@example.com · after run #47

Retry survival · same event twice

Retry survival: 1 payment · 1 email · 3 side effect(s) survived run 2.

Delivery #1 vs delivery #2 into one fake company. Each outbound action is scored for idempotency (did the second run no-op?) and reversibility (can you undo it?).

3 idempotency fail

3 low reversibility

Run #1

Run #1: 1 invoice + 1 email + 1 message

3 external actions

  • Create Invoice · payment
  • Email Customer · email
  • Notify Slack · message

Run #2

Run #2: 1 invoice + 1 email + 1 message

3 external actions

  • Create Invoice · payment
  • Email Customer · email
  • Notify Slack · message

What survived the second run

  • Create Invoicepaymentidempotency failreversibility low

    Run 1×1 → run 2×1. Second delivery creates another payment object. Hard to reverse cleanly.

  • Email Customeremailidempotency failreversibility low

    Run 1×1 → run 2×1. Second delivery sends the email again. You cannot unsend it.

  • Notify Slackmessageidempotency failreversibility low

    Run 1×1 → run 2×1. Second delivery posts again. Chat noise, hard to scrub.

Real-world actions

What would leave your company if this ran.

  • Payment / billingCreate Invoice

    Talks to Stripe to create a invoice. This can move money or create invoices.

  • Customer emailEmail Customer

    Sends an email to a value from the data ("customerEmail") - set when the workflow runs. Subject: Your invoice. This is a real message leaving your system - not a draft inside n8n.

  • Team messageNotify Slack

    Posts a message to Slack (#ops). Your team (or a channel) will see it.

Simulations

4 happy-path steps · 3 external action(s)

Duplicate trigger delivery

FAIL

Retry survival: 1 payment · 1 email · 3 side effect(s) survived run 2.

Spam burst (10 triggers)

FAIL

10 trigger fires produced 30 external action(s) (3+3+3+3+3+3+3+3+3+3 per run). 27 still fired after delivery #1. Ledger: 10 identical emails to customer@example.com with subject "Your invoice".

Missing email fields

FAIL

Missing email caused send to abort mid-flow - customer path is not guarded cleanly.

Fail after first side effect

FAIL

After stripe_invoice_create, a later step failed - partial completion risk confirmed in simulation.

Empty trigger payload

FAIL

Empty trigger data still produced 1 external action(s).

Fake-company stress (50 runs)

FAIL

Across 50 simulated runs: 50 near-identical chat messages posted.

Happy-path timeline (16 events)
  1. 0Scenario "Happy-path simulation" - firing trigger 1 time(s) against fake company
  2. 1Trigger run #1
  3. 2Enter "Payment Webhook" (n8n-nodes-base.webhook)
  4. 3Trigger fired (mocked)
  5. 4"Payment Webhook" → "Create Invoice"
  6. 5Enter "Create Invoice" (n8n-nodes-base.stripe)
  7. 6stripe invoice.create mocked → stripe_1
  8. 7SIDE EFFECT: stripe_invoice_create
  9. 8"Create Invoice" → "Email Customer"
  10. 9Enter "Email Customer" (n8n-nodes-base.gmail)
  11. 10Email mocked → customer@example.com (msg_2)
  12. 11SIDE EFFECT: send_email
  13. 12"Email Customer" → "Notify Slack"
  14. 13Enter "Notify Slack" (n8n-nodes-base.slack)
  15. 14Would send slack message to #ops
  16. 15SIDE EFFECT: post_message

What to fix

  • criticalerror-handlingCreate Invoice

    "Create Invoice" can fail with no backup path

    stripe can fail (timeout, rate limit, auth). No continue-on-fail / error output, and no global error workflow.

    Why it matters: Money or invoices can stop mid-flight after earlier steps already ran - books and reality diverge.

    What to do: Turn on retry for transient SMTP/API errors, and route hard failures to an error branch that alerts someone.

  • criticalidempotencyCreate Invoice

    "Create Invoice" retries can create duplicates

    Retry is on (up to 5 tries) on a create/send action. Each retry can fire again.

    Why it matters: Flaky networks turn into double emails, double Slack pings, or double charges.

    What to do: Before create/send: check "already processed?" using a unique event/message id. Prefer upserts over creates.

  • criticalduplicatesPayment Webhook

    Webhook "Payment Webhook" can fire side effects twice

    Providers often retry webhooks. Downstream create/send nodes have no obvious "already handled this event?" check.

    Why it matters: Duplicate delivery can mean double charges or double customer emails.

    What to do: Store the provider event id; if you've seen it, skip every create/send node.

  • criticalsimulation

    Retry survival: 3 side effect(s) still fire on delivery #2

    Same trigger delivered twice (webhook retry / double submit). Side effects are scored for idempotency and reversibility.

    Why it matters: Retry survival: 1 payment · 1 email · 3 side effect(s) survived run 2.

    What to do: Add dedupe keys, idempotency, and rate limiting / a queue before outbound sends and Stripe writes.

  • criticalsimulation

    Simulation failed: Spam burst (10 triggers)

    Trigger is hit 10 times in a burst into one fake company.

    Why it matters: 10 trigger fires produced 30 external action(s) (3+3+3+3+3+3+3+3+3+3 per run). 27 still fired after delivery #1. Ledger: 10 identical emails to customer@example.com with subject "Your invoice".

    What to do: Add dedupe keys, idempotency, and rate limiting / a queue before outbound sends and Stripe writes.

  • criticalsimulation

    Fake-company ledger: 50× blast radius

    Across 50 simulated runs: 50 near-identical chat messages posted.

    Why it matters: 50 near-identical chat messages posted.

    What to do: Treat every outbound node as dangerous under retries. Require an idempotency key (order id / message id) before send/charge/write.

  • higherror-handling

    Nobody gets alerted when this workflow fails

    There is no Error Trigger and no workflow-level Error Workflow. If a node dies mid-run, the failure can vanish into the execution log.

    Why it matters: You may think an email or invoice finished when it actually stopped halfway - and no one is paged.

    What to do: In n8n Settings, set an Error Workflow (or add an Error Trigger flow) that Slack/emails your team with the failed run link.

  • higherror-handlingEmail Customer

    "Email Customer" can fail with no backup path

    gmail can fail (timeout, rate limit, auth). No continue-on-fail / error output, and no global error workflow.

    Why it matters: Customers get silence, duplicate retries, or a half-finished experience with no internal alert.

    What to do: Turn on retry for transient SMTP/API errors, and route hard failures to an error branch that alerts someone.

  • higherror-handlingNotify Slack

    "Notify Slack" can fail with no backup path

    slack can fail (timeout, rate limit, auth). No continue-on-fail / error output, and no global error workflow.

    Why it matters: Customers get silence, duplicate retries, or a half-finished experience with no internal alert.

    What to do: Turn on retry for transient SMTP/API errors, and route hard failures to an error branch that alerts someone.

  • highsimulation

    Simulation failed: Missing email fields

    Trigger payload has empty/null email fields.

    Why it matters: Missing email caused send to abort mid-flow - customer path is not guarded cleanly.

    What to do: Validate recipient with an IF before any send node.

  • highsimulation

    Simulation failed: Fail after first side effect

    After the first external action, a later outbound step is forced to fail.

    Why it matters: After stripe_invoice_create, a later step failed - partial completion risk confirmed in simulation.

    What to do: Add compensating actions and alerts when a later step dies after an earlier side effect.

  • mediumdata-qualityEmail CustomertoEmail / sendTo

    "Email Customer" recipient comes from live data

    To is dynamic: ={{$json.customerEmail}}. If that field is empty or wrong, the send still runs.

    Why it matters: A bad From/email field can bounce, leak to the wrong person, or fail silently depending on SMTP settings.

    What to do: Add an IF node: only send when the address looks like a real email. Otherwise alert ops.

  • mediumsimulation

    Simulation failed: Empty trigger payload

    Trigger yields nearly empty JSON.

    Why it matters: Empty trigger data still produced 1 external action(s).

    What to do: Add guards so empty/bad trigger data cannot reach outbound nodes.

Got an n8n workflow that looks fine once?

Paste the JSON. We replay retries into a fake company and show what still fires on delivery #2.