Cancel a run with CancelRun or an SDK client, with an optional grace period of 0 to 3,600 seconds (default 300):
await client.cancel(runId, { gracePeriodSeconds: 60 })grace := 60
run, err := c.Cancel(ctx, runID, workflows.CancelOptions{GracePeriodSeconds: &grace})client.cancel(run_id, grace_period_seconds=60)The answer is the run, with status cancelling. Cancelling a run that has already ended is
409 run_not_running.
What happens
- Waiting stops at once. Sleeps, callbacks and child workflows the run is waiting on are cancelled, and so are its running children.
- The workflow sees a cancellation error at the step it’s waiting on:
CancelledErrorin TypeScript, an error matchingworkflows.ErrCancelledin Go, andRunCancelledErrorin Python. Its code isworkflows.cancelled. - Cleanup runs within the grace period, which starts when the cancellation first reaches your
code. In a
catchorfinallyblock (exceptin Python, a check of the error in Go), the workflow can runrunsteps, with their usual retries, to undo or report work. Any other step fails at once. - The run ends
cancelledwhen the workflow returns, whatever it returns, or when the grace period ends.
try {
await step.run("provision", () => provision(order))
await step.sleep("trial", "14d")
} catch (e) {
if (e instanceof CancelledError) await step.run("deprovision", () => deprovision(order))
throw e
}Steps already running
A cancel never interrupts a step that’s already running in your code. Its result is recorded if it arrives within the grace period. On a pull worker, the worker learns of the cancel from its heartbeats and signals the running step, so a long step can stop early:
- TypeScript: the step’s
signalaborts with aCancelledError. - Go: the
StepContextis cancelled, andcontext.Causeisworkflows.ErrCancelled. - Python:
ctx.step.cancelled()turns true.
No new step starts in that invocation; cleanup runs in the next one.