Skip to content

task run --wait can return the PREVIOUS attempt's completion.json when re-running the same task_id (false negative after a fix) #608

Closed

Description

@scttfrdmn

Version: spawn 0.111.1

Summary

spawn task run --spec <f> --wait can return the previous attempt's verdict when a task is re-run with the same task_id, because both runs write the same completion.json key. The caller sees a completed/failed state — with the old timestamps — while the new instance is still running.

Reproduction

Run a spec, have it fail, fix the spec, re-run the same spec (same task_id):

$ spawn task run --spec plink.task.json --region us-west-2 --wait
State:      failed
Exit code:  141
Started:    2026-09-20T03:45:12Z      <-- the PREVIOUS attempt
Ended:      2026-09-20T03:45:57Z

Meanwhile the new instance was alive and went on to succeed:

$ aws ec2 describe-instances ... --query '...InstanceType==`c8g.large`'
i-0643ff223a256a1db   2026-09-20T03:48:53+00:00     # launched AFTER --wait already "answered"

$ aws s3 cp s3://spawn-results-.../tasks/cookbook-plink-r1/completion.json -
{"state":"completed","exit_code":0,"started_at":"2026-09-20T03:49:06Z", ...}

So --wait reported failed 141 for a run that completed 0. Hit twice in one session (two different recipes), and both times the natural read was "my fix didn't work" — I started re-debugging a task that was succeeding as I watched.

Why it matters

This is a false negative in the one place that is supposed to be authoritative. The failure mode is quiet and plausible: the stale record is a real record of a real earlier failure, so nothing looks corrupt — it just describes the wrong run. Re-running after a fix is the single most common reason to invoke --wait, which is exactly when the stale record is most likely to exist and most likely to mislead.

Worth noting this repo's consumer already hit the same class of problem on its own wrapper and fixed it there (make run: never silently return a cached result on re-run), which suggests the raw CLI deserves the same treatment.

Ask

Make --wait refuse to report a completion that predates the run it just launched. Options, in rough order of preference:

  1. Record a run id / launch timestamp and have --wait ignore any completion.json whose started_at (or run id) precedes the current invocation.
  2. Clear or version the completion key at launch — delete completion.json before the instance starts, or write to completion-<runid>.json and have --wait watch that key.
  3. At minimum, warn: if --wait finds a completion that predates launch, say so loudly rather than returning it as the answer.

Happy to re-test against a fix — I re-run same-task_id specs constantly while iterating on recipes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions