{"record":{"id":"c73aa267cd95a6d2","repo":"micro/go-micro","slug":"run-s-is-waiting-at-unknown-step-q","errorCode":null,"errorMessage":"run %s is waiting at unknown step %q","messagePattern":"run (.+?) is waiting at unknown step %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"flow/steps.go","lineNumber":529,"sourceCode":"\t\treturn err\n\t}\n\tif f.checkpoint == nil {\n\t\treturn fmt.Errorf(\"flow %s has no checkpoint configured\", f.name)\n\t}\n\trun, ok, err := f.checkpoint.Load(ctx, runID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !ok {\n\t\treturn fmt.Errorf(\"run %s not found\", runID)\n\t}\n\tif run.Status != \"waiting\" {\n\t\treturn fmt.Errorf(\"run %s is not waiting for input (status %q)\", runID, run.Status)\n\t}\n\tsteps := f.opts.Steps\n\ti := stepIndex(steps, run.State.Stage)\n\tif i < 0 {\n\t\treturn fmt.Errorf(\"run %s is waiting at unknown step %q\", runID, run.State.Stage)\n\t}\n\t// The awaited step is satisfied by the injected input; record it done and\n\t// advance so runFrom re-enters at the next step.\n\trun.Steps[i].Status = \"done\"\n\trun.Steps[i].Result = truncate(input, 200)\n\trun.State.Data = []byte(input)\n\tif i+1 < len(steps) {\n\t\trun.State.Stage = steps[i+1].Name\n\t} else {\n\t\trun.State.Stage = \"\"\n\t}\n\trun.Await = nil\n\trun.Status = \"running\"\n\t_, err = f.runFrom(ctx, run)\n\treturn err\n}\n\n// runFrom executes steps from the run's current Stage to the end,","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/flow/steps.go#L511-L547","documentation":"ResumeWith resumes a run waiting for input by marking the awaited step done and advancing. If the run's persisted State.Stage doesn't match any step in the flow's current Steps configuration (stepIndex < 0), the library cannot identify which step the input satisfies and returns this error. It almost always means the flow definition and the persisted run state have drifted apart.","triggerScenarios":"Calling flow.ResumeWith(ctx, runID, input) where run.State.Stage names a step absent from f.opts.Steps — the step was renamed/removed in a deploy, or the run was created by a differently configured flow sharing the same checkpoint store.","commonSituations":"Deploying a new flow version with renamed steps while waiting runs persist across restarts; resuming a run with a different Flow instance than the one that started it; multiple flow definitions writing to one checkpoint store without namespacing.","solutions":["Restore the persisted step name in the flow's Steps so State.Stage matches again.","Migrate the stale run: update run.State.Stage in the checkpoint store to a valid step name, or expire the run.","Version flows (distinct flow names/checkpoint keys per definition version) so old runs resume against their matching definition.","Drain all waiting runs via ResumeWith before deploying step renames or deletions."],"exampleFix":"// before (deployed rename)\nflow.Steps(flow.Step{Name: \"review-v2\", Run: review}) // runs wait at \"review\"\n\n// after (keep original name)\nflow.Steps(flow.Step{Name: \"review\", Run: review})","handlingStrategy":"validation","validationCode":"run, _, err := ckpt.Load(ctx, runID)\nif err == nil && stepIndex(f.opts.Steps, run.State.Stage) < 0 {\n    return fmt.Errorf(\"run %s waits at unknown step %q; cannot inject input\", runID, run.State.Stage)\n}","typeGuard":"func stageKnown(steps []flow.Step, stage string) bool { return stepIndex(steps, stage) >= 0 }","tryCatchPattern":"if _, err := f.ResumeWith(ctx, runID, input); err != nil {\n    if strings.Contains(err.Error(), \"waiting at unknown step\") {\n        // stale run from an old flow definition; expire or migrate it\n        return expireRun(ctx, runID)\n    }\n    return err\n}","preventionTips":["Freeze step names once flows are live; add new steps instead of renaming","Version flow definitions so waiting runs resume against their own schema","Alert on 'unknown step' errors — they signal definition/run state drift","Drain waiting runs before deploys that alter step names"],"tags":["go","flow","resume","schema-drift"],"backgroundTag":"checkpoint-state-drift","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}