Reference

Troubleshooting.

Common issues operators hit, with the actual fix. If your problem isn't here, hit reply on any Backstop email — a founder reads everything within one business day.

“My Stripe connection isn't active.”

We run a background health probe against your connected Stripe account and record the result on the connection. The dashboard surfaces a banner when it's not healthy. Three states worth knowing:

Disconnected (access revoked)

Someone on your Stripe team revoked the Backstop integration, or (api-key mode) the restricted key was rolled. Our probe gets a 401 and we stop processing your webhooks. Reconnect from Dashboard → Connect Stripe; we'll re-mirror everything we missed.

Restricted (charges or payouts disabled)

Stripe restricted your account — charges_enabled or payouts_enabledis false. We can still read your data, but you have homework on Stripe's side (usually identity/verification) before retries will succeed. Resolve it in your Stripe dashboard; the banner clears on the next health check.

“We haven't heard from your Stripe in 24h”

If even the health probe can't reach Stripe, the dashboard flags the stale check. This is usually a transient Stripe-side or network issue — if it persists past a day, hit reply.

“My customers aren't syncing.”

Three usual causes, in order of likelihood:

1. The connection was revoked

Same root cause as “disconnected” above. Reconnect from Dashboard → Connect Stripe; the dashboard shows a red banner when this happens.

2. You're in test mode but watching livemode (or vice versa)

We mirror the mode you connected with. The header shows testmode or livemodebelow your workspace name; if it doesn't match what you expect, reconnect with the right mode (there's no in-product toggle — see below).

3. Webhook delivery to us is failing

Rare, but check Stripe's webhook delivery dashboard for failed sends to our Connect endpoint. If you see 5xx responses from us, hit reply — that's on us to fix.

“No recovery campaigns are showing up.”

A recovery campaign is created when Stripe reports a failed paymenton a subscription invoice. If you don't see any:

  • You may simply have no failures yet. No failed invoice means no campaign — this is the happy path, not a bug. In test mode, create a subscription with a decline-triggering test card to generate one.
  • Check the mode.Test-mode failures only appear when you're connected in test mode, and live-mode failures only in livemode. A mode mismatch is the most common “where are my campaigns” cause.
  • Connection just (re)connected. Right after connecting we backfill, but very recent failures can lag a webhook cycle. Give it a few minutes.
  • Read-only / audit connection.If your connection isn't writable, recovery is intentionally suppressed (no retries, no sends) until write access is granted.

“Dunning emails aren't going out.”

Recovery is paused

Check Settings → Pause recovery. Pausing suppresses dunning email sends across the workspace until a set time (recovery_paused_until); Stripe's built-in retry schedule keeps running underneath — only the obviously-automated email touchpoints pause. The dashboard shows an amber banner while paused, and the schedule still advances so sends resume on time once the pause lifts.

The customer hard-bounced

A hard bounce sets customers.bounced_at, and we suppress all further sends to that address — including dunning — to protect your sender reputation. The recovery schedule still advances; we just don't email a dead address.

The customer unsubscribed

Customers who hit the unsubscribe link get customers.unsubscribed_at set; we then skip the marketing-tone sends — the reactivation / win-back drip and offer-reminder emails. Dunning (the failed-payment recovery sequence) is transactional and bypasses unsubscribe — but customers can still mark dunning as spam, which we honor, and a hard bounce suppresses everything regardless.

A custom send domain is mid-setup

This does not block sends. While your custom send domain is unverified (pending/failed), we automatically fall back to the shared trybackstop.comsender, so dunning keeps going out — it just won't come from your domain until verification lands. If you want emails to come from your domain, finish verification. See Custom send domain.

“Retries seem to be firing twice / on the wrong schedule.”

Backstop runs your retries on the cadence in Settings → Retry policy (soft declines at +3/+5/+7 days, hard declines one retry, capped at 6 attempts within 30 days by default). We schedule these slots ourselves — Stripe's built-in Smart Retries do not run on top of ours. If you also have Stripe Smart Retries enabled in your Stripe dashboard's revenue-recovery settings, you can see overlapping retry attempts and double dunning. Pick one system: keep Stripe's automatic retries offand let Backstop drive, or adjust the Backstop retry policy to match. They're not designed to stack.

“Am I in test or live mode?”

The header under your workspace name reads testmode or livemode. We mirror whichever mode you connected with — and they are completely separate data sets. Test-mode customers, subscriptions, and campaigns never mix with live ones.

“My customer says they can't reach the cancel / update-card page.”

If the customer reports ERR_NAME_NOT_RESOLVED, DNS_PROBE_FINISHED_NXDOMAIN, or a similar “site not found” error — the page itself is up; their network is refusing to resolve trybackstop.com. The two patterns we've seen:

Corporate firewall in newly-registered-domain mode

Some DNS-filtering services (Zscaler, Cisco Umbrella, NextDNS, certain VPNs) quarantine domains under ~30–90 days old. A domain ages out of this window automatically, so if you ever see it on trybackstop.com it is temporary. While a customer is affected, they can:

You want to skip this class of issue entirely

Configure a custom portal domain on your own subdomain (portal.yourcompany.com). Your customers never see trybackstop.com at all, and the domain inherits your established reputation with DNS filters.

“The cancel page is throwing 404.”

Most often: no cancel flow has been published yet. The token is valid but the runtime can't find a flow to render. Go to Cancel flows → New flow, pick a starter template, click Publish. Default traffic is 100% on v1 once you publish.

Less often: the token expired or was already consumed. Embed cancel links last 24 hours; cancel/card-update links minted elsewhere last 21 days. Re-mint via the portal-link button on the customer's drilldown.

“Embed snippet returns signature_required.”

Your workspace has embed_require_signature=true but the request either had no signature or the signature failed verification. The usual culprits:

Copy-paste signing snippets (Node, and the “{ url } means it worked” check) live in the embed snippet doc.

“Save rate looks wrong.”

Save rate is computed as saved / (saved + canceled), excluding abandoned sessions. (A “saved” outcome is any of saved_discount, saved_pause, saved_downgrade, or saved_other.) If your dashboard shows 0% but you're sure you saved someone, check that the session reached a terminal step — abandoning at the survey doesn't count toward either side of the ratio.

Still stuck?

Hit reply on any email from us. Include the workspace slug and a screenshot if you have one. We answer within one business day.