anomalyco/sst · error · StopError

Failed to stop task

Error message

Failed to stop task

What it means

`task.stop` calls the ECS StopTask API via awsFetch. If the HTTP response is not OK, a `StopError` with message "Failed to stop task" is thrown; the raw `Response` is attached as `error.response` so the AWS error body can be examined (e.g. AccessDeniedException, invalid ARN).

Source

Thrown at sdk/js/src/aws/task.ts:330

   * [`StopTask`](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_StopTask.html).
   */
  export async function stop(
    resource: Resource,
    task: string,
    options?: Options
  ): Promise<StopResponse> {
    const res = await awsFetch("ecs", "/", {
      method: "POST",
      headers: {
        "X-Amz-Target": "AmazonEC2ContainerServiceV20141113.StopTask",
        "Content-Type": "application/x-amz-json-1.1",
      },
      body: JSON.stringify({
        cluster: resource.cluster,
        task,
      }),
    }, options);
    if (!res.ok) throw new StopError(res);

    const data = (await res.json()) as {
      task: {
        taskArn: string;
        lastStatus: string;
      };
    };
    if (!data.task) throw new StopError(res);

    return {
      arn: data.task.taskArn,
      status: data.task.lastStatus,
      response: data,
    };
  }

  export class DescribeError extends Error {
    constructor(public readonly response: Response) {

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Read `error.response` body for the exact AWS error code.
  2. Grant the caller's IAM role `ecs:StopTask` on the cluster.
  3. Check the task's current state with `task.describe` first — if already stopped, skip the stop call.
  4. Verify the ARN is complete and belongs to `resource.cluster`.

Example fix

const current = await task.describe(Resource.MyTask, arn);
if (current.status !== "STOPPED") {
  await task.stop(Resource.MyTask, arn);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const status = await task.describe(Resource.MyTask, arn).catch(() => null);
if (!status || status.status === "STOPPED") return; // nothing to stop

Type guard

function isStopError(e: unknown): e is task.StopError {
  return e instanceof task.StopError && typeof e.response === "object";
}

Try / catch

try {
  await task.stop(Resource.MyTask, arn);
} catch (e) {
  if (isStopError(e)) {
    const detail = await e.response.text();
    if (detail.includes("MISSING") || detail.includes("not found")) return; // already stopped
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `task.stop(resource, taskArn)` where the ECS StopTask request returns non-OK: missing IAM `ecs:StopTask` permission, task ARN not found or already stopped, wrong cluster, or malformed ARN.

Common situations: Function's IAM role lacks ecs:StopTask; stopping a task that already completed/stopped (StopTask returns Missing/Invalid ARN); passing a truncated ARN; stopping a task in a different cluster than the linked resource.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/0f4ae72abf272805. Report an issue: GitHub.