micro/go-micro · error

run %s is not waiting for input (status %q)

Error message

run %s is not waiting for input (status %q)

What it means

After loading a waiting run, ResumeWith looks up the run's current stage (run.State.Stage) in the flow's configured steps via stepIndex. A waiting run whose stage doesn't match any configured step cannot be resumed safely, so the library returns this error. It typically means the flow definition changed since the run was persisted.

Source

Thrown at flow/steps.go:524

func (f *Flow) ResumeWith(ctx context.Context, runID, input string) error {
	ctx, cancel := f.withTimeout(ctx)
	defer cancel()

	if err := validateSteps(f.opts.Steps); err != nil {
		return err
	}
	if f.checkpoint == nil {
		return fmt.Errorf("flow %s has no checkpoint configured", f.name)
	}
	run, ok, err := f.checkpoint.Load(ctx, runID)
	if err != nil {
		return err
	}
	if !ok {
		return fmt.Errorf("run %s not found", runID)
	}
	if run.Status != "waiting" {
		return fmt.Errorf("run %s is not waiting for input (status %q)", runID, run.Status)
	}
	steps := f.opts.Steps
	i := stepIndex(steps, run.State.Stage)
	if i < 0 {
		return fmt.Errorf("run %s is waiting at unknown step %q", runID, run.State.Stage)
	}
	// The awaited step is satisfied by the injected input; record it done and
	// advance so runFrom re-enters at the next step.
	run.Steps[i].Status = "done"
	run.Steps[i].Result = truncate(input, 200)
	run.State.Data = []byte(input)
	if i+1 < len(steps) {
		run.State.Stage = steps[i+1].Name
	} else {
		run.State.Stage = ""
	}
	run.Await = nil
	run.Status = "running"

View on GitHub (pinned to 24529f1404)

Solutions

  1. Restore the original step name in the flow definition so the persisted stage matches a configured step.
  2. Migrate old waiting runs: either let them fail out, or manually update run.State.Stage in the checkpoint store to a valid step name.
  3. Use flow versioning (separate flow names or separate checkpoint keys per version) so old runs resume against their matching definition.
  4. Before deploy, drain waiting runs (call ResumeWith for each) so no runs persist across the step-rename.

Example fix

// before (deployed rename)
flow.Steps(flow.Step{Name: "approve-v2", Run: approve}) // old runs wait at "approve"

// after (keep old name or add alias step)
flow.Steps(flow.Step{Name: "approve", Run: approve})
Defensive patterns

Strategy: validation

Validate before calling

run, _, _ := ckpt.Load(ctx, runID)
i := stepIndex(f.opts.Steps, run.State.Stage)
if i < 0 {
    return fmt.Errorf("waiting run %s references unknown step %q; flow definition changed", runID, run.State.Stage)
}

Type guard

func stepStillConfigured(steps []flow.Step, stage string) bool {
    return stepIndex(steps, stage) >= 0
}

Try / catch

if _, err := f.ResumeWith(ctx, runID, input); err != nil {
    if strings.Contains(err.Error(), "unknown step") {
        // migrate/expire the stale run; do not retry blindly
        return expireRun(ctx, runID)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ResumeWith on a run whose persisted State.Stage names a step that no longer exists in f.opts.Steps — e.g. the step was renamed, removed, or the run was saved by a differently configured flow with the same checkpoint.

Common situations: Deploying a new version of the flow (renamed/deleted a step) while old runs were waiting in the checkpoint store; resuming a run with a Flow instance whose Steps option differs from the one that created it; running multiple flow variants that share a checkpoint store.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/90ed8c87e51b7890. Report an issue: GitHub.