Skip to main content
An AMBIGUOUS effect is one whose executor raised something other than NotExecuted, timed out, or never returned. CTRLRun will not guess, so a person asks the remote and records the answer with ctrlrun resolve. This guide makes one, finds it, resolves it both ways, and shows what the evidence says afterwards. Prerequisites: pip install ctrlrun, an empty directory. The remote is a stand-in that commits and then loses the reply.
1

Make an ambiguous effect

runnable
runnable
2

Find it

runnable
A retry of either is refused with AmbiguousEffect until the record moves. A worker that died mid-call ends here too, when its lease lapses; nothing sweeps and nothing releases.
3

Ask the remote, then say what happened

Look in the Stripe dashboard, or query the DNS zone. Then record the answer. Exactly one of the two flags, and only for an effect that is AMBIGUOUS:
runnable
--committed means the remote did it: a retry is now refused as a duplicate. --failed means it provably did not: a retry is now permitted. Neither undoes anything.
4

Read who resolved it

The resolution is an EFFECT_RESOLVED event carrying resolved_by, and ctrlrun inspect <action_id> shows it in the action’s history:
runnable
A retry after a resolution is a new action with its own receipt; it is never attributed to the resolver.

When to reach for a hook instead

If the remote can be asked programmatically, a reconcile hook asks it for you and moves the record the same way, with the same rule that it moves only in the direction the answer points: Reconcile automatically.

If it didn’t work

  • resolve exits 1 with is not ambiguous: the effect already has a known outcome. A committed effect cannot be moved back to failed, or the other way.
  • resolve exits 1 with nobody reserved: the key is misspelled, or the effect belongs to another store; check --store-url or $CTRLRUN_STATE.
  • exactly one of --committed and --failed: pass one flag.

Next