Manual cancellation
Stop a running workflow execution from the CLI, REST API, or Python SDK — and understand what happens to in-flight tasks when the signal lands.
Cancelling a workflow tells the runtime to stop its execution cleanly. The worker receives the signal, cancels the asyncio task running the workflow, and writes a final CANCELLED state to the execution record. This page covers the three surfaces you use to send that signal: the CLI, the REST API, and the Python SDK.
What happens when you cancel
Cancellation is cooperative. When the server receives a cancel request it:
- Transitions the execution to
CANCELLINGstate and persists the change. - Notifies the worker holding the execution via SSE.
- The worker calls
.cancel()on the asyncio task running the workflow. - Python delivers
asyncio.CancelledErrorat the nextawaitinside the workflow or its tasks. - The
@workflowdecorator catches the error, callsctx.cancel(), and the execution reachesCANCELLED.
The execution record is immutable after that point. Tasks that completed before the signal was delivered keep their recorded outputs; in-flight tasks do not retry.
Cancel from the CLI
flux workflow cancel <workflow-name> <execution-id>
Both arguments are required. <workflow-name> is the registered name of the workflow; <execution-id> is the UUID returned when the execution was started.
flux workflow cancel data_pipeline exec-abc-123
The command returns immediately; it does not wait for the worker to finish unwinding. To confirm the execution reached a terminal state, poll flux execution show <execution-id> until the status is CANCELLED, COMPLETED, or FAILED. If your server is not on localhost:8000, pass --server-url:
flux workflow cancel data_pipeline exec-abc-123 --server-url http://my-server:8000
The CLI accepts one optional flag:
| Flag | Default | Description |
|---|---|---|
--server-url | http://localhost:8000 | Flux server to connect to. |
Cancel via the REST API
The cancel endpoint follows the same pattern as other execution-scoped routes:
GET /workflows/{namespace}/{workflow_name}/cancel/{execution_id}
The HTTP method is GET. Query parameters:
| Parameter | Default | Description |
|---|---|---|
mode | async | async returns immediately; sync blocks until the execution is terminal. |
detailed | false | Return the full execution context rather than a summary. |
Example with curl:
curl -X GET \
"http://localhost:8000/workflows/default/data_pipeline/cancel/exec-abc-123?mode=async" \
-H "Authorization: Bearer <api-key>"
A 200 response with mode=async means the cancel request was accepted and queued. The execution may still be CANCELLING for a moment while the worker unwinds. Poll GET /executions/{execution_id} or use mode=sync to wait for the terminal state.
If the execution has already finished, the server returns 400 with "Cannot cancel a finished execution." Cancellation is a no-op on completed, failed, or already-cancelled executions.
Cancel from the Python SDK
FluxClient exposes cancel_execution as an async method:
import asyncio
from flux.client import FluxClient
async def main():
async with FluxClient("http://localhost:8000") as client:
result = await client.cancel_execution(
workflow_ref="default/data_pipeline",
execution_id="exec-abc-123",
)
print(result)
asyncio.run(main())
workflow_ref uses the "namespace/name" format. The method maps to the same REST endpoint as the curl example above.
cancel_execution returns the execution summary dict on success:
{
"execution_id": "exec-abc-123",
"state": "CANCELLING", # or "CANCELLED" if the worker finished immediately
...
}
To confirm the execution reached CANCELLED rather than stopping at CANCELLING, either poll client.get_execution(execution_id) or use a mode=sync workaround by calling the REST endpoint directly via the underlying httpx client.
Checking the result
After sending the cancel request, retrieve the final state:
# CLI — inspect a single execution by ID
flux execution show exec-abc-123 --detailed
# REST
curl "http://localhost:8000/executions/exec-abc-123" -H "Authorization: Bearer <api-key>"
(flux workflow show <name> takes only the workflow name plus an optional --version; it doesn’t accept an execution ID. Use flux execution show for execution-level details.)
The state field will be one of:
| State | Meaning |
|---|---|
CANCELLING | Signal delivered; worker still unwinding. |
CANCELLED | Terminal. Execution stopped cleanly. |
COMPLETED | Execution finished before the signal landed. |
FAILED | Execution failed (independently of the cancel request). |
What to read next
- Reliability → Cancellation — how task and workflow code handles
asyncio.CancelledError, runs cleanup infinallyblocks, and keeps state consistent. - Reference: flux workflow cancel — full CLI flag reference.
- Pause and resume — suspend a workflow at a named checkpoint rather than stopping it entirely.