---
title: "Cancellation"
description: "Cancel a run, and run cleanup steps within a grace period."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.ezghcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cancellation

Cancel a run with [CancelRun](/workflows-api/CancelRun/) or an SDK client, with an optional
grace period of 0 to 3,600 seconds (default 300):

### TypeScript

```ts
await client.cancel(runId, { gracePeriodSeconds: 60 })
```
### Go

```go
grace := 60
run, err := c.Cancel(ctx, runID, workflows.CancelOptions{GracePeriodSeconds: &grace})
```
### Python

```python
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

1. **Waiting stops at once.** Sleeps, callbacks and child workflows the run is waiting on are
   cancelled, and so are its running children.
2. **The workflow sees a cancellation error** at the step it's waiting on: `CancelledError` in
   TypeScript, an error matching `workflows.ErrCancelled` in Go, and `RunCancelledError` in Python.
   Its code is `workflows.cancelled`.
3. **Cleanup runs within the grace period,** which starts when the cancellation first reaches your
   code. In a `catch` or `finally` block (`except` in Python, a check of the error in Go), the
   workflow can run `run` steps, with their usual retries, to undo or report work. Any other step
   fails at once.
4. **The run ends `cancelled`** when the workflow returns, whatever it returns, or when the grace
   period ends.

```ts
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](/workflows/pull-workers), 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 `signal` aborts with a `CancelledError`.
- **Go:** the `StepContext` is cancelled, and `context.Cause` is `workflows.ErrCancelled`.
- **Python:** `ctx.step.cancelled()` turns true.

No new step starts in that invocation; cleanup runs in the next one.

Source: https://docs.ezghcloud.com/workflows/cancellation/index.mdx
