micro/go-micro · error
agent run %s is terminal with status %q
Error message
agent run %s is terminal with status %q
What it means
agent.Resume refuses to continue runs already in a terminal state (e.g. "failed", "canceled") other than "done". Terminal runs have concluded and cannot be re-executed; the error includes the actual status so the caller can decide what to do. Only non-terminal (running/paused in resumable stages) or done runs are resumable.
Source
Thrown at agent/checkpoint.go:104
if !ok {
return nil, fmt.Errorf("agent run %s not found", runID)
}
if run.Status == "paused" {
if run.State.Stage == agentInputStep {
return nil, fmt.Errorf("agent run %s is input-required; resume with ResumeInput", runID)
}
run.Status = "running"
run.State.Stage = agentAskStep
}
if run.Status == "done" {
var resp Response
if err := json.Unmarshal(run.State.Data, &resp); err != nil {
return nil, fmt.Errorf("agent run %s response decode: %w", runID, err)
}
return &resp, nil
}
if terminalAgentRunStatus(run.Status) {
return nil, fmt.Errorf("agent run %s is terminal with status %q", runID, run.Status)
}
message := string(run.State.Data)
parentID := run.ParentID
a.mu.Lock()
defer a.mu.Unlock()
if a.model == nil {
a.setup()
}
return a.askLocked(ctx, run.ID, message, parentID, &run, false)
}
// ResumeInput resumes a checkpointed agent run that paused via the built-in
// request_input tool. The supplied input is appended to the original request so
// the same run can continue with durable checkpoint and completed tool history.
func ResumeInput(ctx context.Context, ag Agent, runID, input string) (*Response, error) {
a, ok := ag.(*agentImpl)
if !ok {
return nil, fmt.Errorf("agent resume input: unsupported agent implementation %T", ag)View on GitHub (pinned to 24529f1404)
Solutions
- Do not resume; treat the run as finished and start a new agent run with the original or amended message.
- Check the run's status in the checkpoint store before calling Resume and skip terminal runs in retry loops.
- If the run failed transiently, create a fresh run (new runID) rather than resuming the failed one.
Example fix
// before
resp, err := agent.Resume(ctx, ag, runID) // status: canceled
// after
run, ok, _ := ckpt.Load(ctx, runID)
if ok && isTerminal(run.Status) {
runID = "" // start fresh
}
resp, err = ag.Run(ctx, message) Defensive patterns
Strategy: validation
Validate before calling
run, ok, _ := ckpt.Load(ctx, runID)
if ok && (run.Status == "failed" || run.Status == "canceled") {
return fmt.Errorf("run %s already terminal; start a new run", runID)
} Type guard
func isResumable(r flow.Run) bool {
switch r.Status {
case "running", "paused", "":
return r.Status != "paused" || r.State.Stage != "input-required"
default:
return false
}
} Try / catch
resp, err := agent.Resume(ctx, ag, runID)
if err != nil && strings.Contains(err.Error(), "is terminal") {
// mark job permanently failed; do not retry
} Prevention
- Filter out terminal runs in retry/scheduler loops.
- Check status before resuming; treat terminal as final.
- Start fresh runs instead of resuming failed ones.
When it happens
Trigger: Calling agent.Resume with a runID whose checkpointed run has a terminal status such as "failed" or "canceled", as checked by terminalAgentRunStatus.
Common situations: Replaying old run IDs from an incident or migration; a scheduler retrying resumes for runs that were canceled by another component; double-processing in queues where the run already failed permanently.
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 terminal with status
- agent: checkpointed run is input-required; resume with Resum
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/e0417bb638bf43bb.
Report an issue: GitHub.