micro/go-micro · error
agent: checkpointed run is terminal with status
Error message
agent: checkpointed run is terminal with status
What it means
The checkpointed run is in a terminal state (per terminalAgentRunStatus), so it cannot be resumed. Terminal runs have finished (successfully, failed, or otherwise permanently stopped) and no further work can be streamed.
Source
Thrown at agent/stream.go:159
if a.opts.Checkpoint == nil {
return nil, errors.New("agent: ResumeStreamAsk requires a checkpoint")
}
run, ok, err := a.opts.Checkpoint.Load(ctx, runID)
if err != nil {
return nil, err
}
if !ok {
return nil, errors.New("agent: checkpointed run not found")
}
if run.Status == "done" {
var resp Response
if err := json.Unmarshal(run.State.Data, &resp); err != nil {
return nil, err
}
return &resp, nil
}
if terminalAgentRunStatus(run.Status) {
return nil, errors.New("agent: checkpointed run is terminal with status " + run.Status)
}
a.mu.Lock()
defer a.mu.Unlock()
if a.tools == nil {
a.tools = ai.NewTools(a.opts.Registry, ai.ToolClient(a.opts.Client))
}
base := a.toolHandler()
handler := func(ctx context.Context, call ai.ToolCall) ai.ToolResult {
_ = sendStreamEvent(ctx, events, &StreamEvent{Type: StreamEventToolStart, ToolCall: call})
result := base(ctx, call)
_ = sendStreamEvent(ctx, events, &StreamEvent{Type: StreamEventToolEnd, ToolCall: call, Result: result})
return result
}
a.setupWithToolHandler(handler)
defer a.setupWithToolHandler(nil)
if run.Status == "paused" {
if run.State.Stage == agentInputStep {View on GitHub (pinned to 24529f1404)
Solutions
- Inspect run.Status via Checkpoint.Load before resuming and only resume non-terminal runs
- Treat terminal failed runs as unrecoverable: start a new run instead
- If the run completed, load and return the persisted Response rather than resuming
Example fix
// before
stream, err := agent.ResumeStreamAsk(ctx, ag, runID)
// after
run, ok, _ := store.Load(ctx, runID)
if ok && run.Status == "failed" {
return startNewRun(ctx, ag) // don't resume a terminal run
}
stream, err := agent.ResumeStreamAsk(ctx, ag, runID) Defensive patterns
Strategy: validation
Validate before calling
run, ok, _ := store.Load(ctx, runID)
if ok && run.Status != "running" && run.Status != "paused" {
return fmt.Errorf("run %s is terminal (%s); cannot resume", runID, run.Status)
} Try / catch
stream, err := agent.ResumeStreamAsk(ctx, ag, runID)
if err != nil && strings.Contains(err.Error(), "terminal with status") {
return fmt.Errorf("run already finished; fetch result or start a new run")
} Prevention
- Check run.Status before resuming; only resume non-terminal runs
- Handle the "done" case by loading the persisted Response instead of resuming
- Guard against double-resume with per-run locks or status transitions in your orchestration
When it happens
Trigger: Calling ResumeStreamAsk/ResumeStream on a run whose stored Status is a terminal value other than "done" (e.g. failed/canceled status), after that status was persisted by a prior run.
Common situations: Retrying a resume after the run already failed; double-resuming a canceled run; race where another process terminated the run between status check and resume.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- agent: ResumeStreamAsk unsupported by implementation
- agent: ResumeStreamAsk requires a checkpoint
- agent: checkpointed run not found
- agent: checkpointed run is input-required; resume with Resum
- agent resume pending: unsupported agent implementation %T
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/1dd456bb47ca3b92.
Report an issue: GitHub.