anomalyco/sst · error · StopError
Failed to stop workflow
Error message
Failed to stop workflow
What it means
Thrown by the public `stop` function when the POST to `/2025-12-01/durable-executions/{arn}/stop` returns a non-OK HTTP status. It wraps the raw Response so the caller can inspect status and body. This means the execution was not stopped — it may still be running and consuming retries/time.
Source
Thrown at sdk/js/src/aws/workflow.ts:396
): Promise<StopResponse> {
const response = await awsFetch(
"lambda",
`/2025-12-01/durable-executions/${encodeURIComponent(arn)}/stop`,
{
method: "POST",
headers: input?.error
? {
"Content-Type": "application/json",
}
: undefined,
body:
input?.error === undefined
? undefined
: JSON.stringify(normalizeError(input.error)),
},
options,
);
if (!response.ok) throw new StopError(response);
const data = (await response.json()) as StopInvocationResponse;
return {
arn,
status: "STOPPED",
stoppedAt:
data.StopTimestamp === undefined
? undefined
: parseTimestamp(data.StopTimestamp),
};
}
/**
* Send a successful result for a pending workflow callback.
*
* This is the equivalent to calling
* [`SendDurableExecutionCallbackSuccess`](https://docs.aws.amazon.com/lambda/latest/api/API_SendDurableExecutionCallbackSuccess.html).
*/View on GitHub (pinned to a0bd20f762)
Solutions
- Check the wrapped response status — 404/409 usually means the execution already terminated, which may be acceptable; treat idempotently.
- Verify IAM permissions for stopping durable executions in the target region/account.
- Retry 429/5xx with backoff before giving up.
- Validate the optional `input.error` object matches the expected shape ({ errorType, errorMessage }) when passing it.
Example fix
// before
await stop(arn); // throws if already stopped
// after
try {
await stop(arn, { error: { errorType: "Cancelled", errorMessage: "user cancelled" } });
} catch (err) {
if (err instanceof StopError && [404, 409].includes(err.response.status)) return; // already terminal
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
// check current state first; skip stop if already terminal
const current = await describe(arn).catch(() => null);
if (!current || ["SUCCEEDED", "FAILED", "STOPPED"].includes(current.status)) {
return; // nothing to stop
} Type guard
function isStopError(err: unknown): err is StopError {
return err instanceof StopError && typeof err.response?.status === "number";
} Try / catch
try {
await stop(arn, { error: { errorType: "Cancelled", errorMessage: "user requested stop" } });
} catch (err) {
if (err instanceof StopError && [404, 409].includes(err.response.status)) {
return; // already terminal — treat stop as idempotent
}
if (err instanceof StopError && (err.response.status === 429 || err.response.status >= 500)) {
return retryWithBackoff(() => stop(arn));
}
throw err;
} Prevention
- Design stop flows to be idempotent — a 404/409 after stop usually means the execution finished first.
- Pass a structured input.error ({ errorType, errorMessage }) so the API accepts the body.
- Verify IAM includes the durable-execution stop action in the target region.
- Avoid concurrent workers stopping the same execution without coordination.
When it happens
Trigger: Calling `Workflow.stop(arn)` where: (1) the ARN does not exist or was already completed (404/409 — execution already SUCCEEDED/FAILED/STOPPED); (2) credentials lack the stop permission (`lambda:StopDurableExecution`); (3) throttling (429) or transient 5xx; (4) malformed error payload in `input.error` rejected by the API.
Common situations: Race condition where the workflow finished before the stop call landed; cancelling stale executions from a cleanup script against the wrong region; IAM policy missing the durable-execution stop action; double-stopping the same execution from concurrent workers.
Related errors
- Failed to describe workflow
- Failed to succeed workflow callback
- Failed to fail workflow callback
- You must provide a KMS key via `kmsKey` when configuring `cu
- Cannot set both "logging.retention" and "logging.logGroup"
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/dca6c4fcf88daa18.
Report an issue: GitHub.