micro/go-micro · error

agent run %s has unfinished plan steps: %s

Error message

agent run %s has unfinished plan steps: %s

What it means

Before continuing a checkpointed run, the agent checks for unfinished plan steps (agent/agent.go:552). If any remain, it marks the run failed, saves state so a later resume restarts from the saved input message, and returns this error listing the unfinished step names. It prevents skipping half-completed plan work.

Source

Thrown at agent/agent.go:552

			reply += "\n\n"
		}
		reply += resp.Answer
	}

	completedToolCalls := checkpointToolCalls(run.Steps)
	if a.currentRun != nil {
		completedToolCalls = checkpointToolCalls(a.currentRun.Steps)
	}
	res := &Response{
		Reply:     reply,
		ToolCalls: mergeCheckpointToolCalls(completedToolCalls, resp.ToolCalls),
		Agent:     a.opts.Name,
		RunID:     a.runID,
		ParentID:  parentRunID,
	}
	if a.opts.Checkpoint != nil {
		if unfinished := a.unfinishedPlanSteps(); len(unfinished) > 0 {
			err = fmt.Errorf("agent run %s has unfinished plan steps: %s", run.ID, strings.Join(unfinished, ", "))
			run.Status = "failed"
			run.State.Stage = agentAskStep
			run.State.Data = []byte(message)
			if a.currentRun != nil {
				run.Steps = a.currentRun.Steps
			}
			if len(run.Steps) == 0 {
				run.Steps = []flow.StepRecord{{Name: agentAskStep}}
			}
			run.Steps[0].Status = "failed"
			run.Steps[0].Error = err.Error()
			_ = a.saveRun(ctx, run)
			return nil, err
		}
	}
	run.Status = "done"
	run.State.Stage = ""
	if b, marshalErr := json.Marshal(res); marshalErr == nil {

View on GitHub (pinned to 24529f1404)

Solutions

  1. Call agent.Resume(ctx, ag, runID) to continue the interrupted plan instead of starting a new Ask
  2. Complete or cancel the outstanding plan steps, then retry the request
  3. Use a fresh agent/run (or clear the checkpoint) if the old plan should be abandoned
  4. Serialize access to the agent — avoid concurrent Ask calls on the same checkpointed agent
  5. Inspect the listed step names in the error to see exactly which work is pending

Example fix

// before
resp, err := ag.Ask(ctx, newMsg) // unfinished plan steps error
// after
resp, err := agent.Resume(ctx, ag, lastRunID) // continue existing plan
if err != nil {
    resp, err = ag.Ask(ctx, newMsg) // only after plan resolved
}
Defensive patterns

Strategy: validation

Validate before calling

// before Ask, ensure no unfinished plan steps on the last checkpointed run
runs, err := agent.Pending(ctx, ag)
if err == nil && len(runs) > 0 {
    // resume those runs first instead of calling Ask
}

Try / catch

resp, err := ag.Ask(ctx, msg)
if err != nil && strings.Contains(err.Error(), "unfinished plan steps") {
    // finish or cancel the plan, or resume the run, then retry
    return recoverPlan(err)
}

Prevention

When it happens

Trigger: Calling Ask/Chat on an agent with Checkpoint configured while a previous run's plan has steps not yet completed (unfinishedPlanSteps() non-empty); also surfaced in streaming tests like TestA2AStreamUsesAgentChatPathWithTools.

Common situations: Reusing an agent mid-plan without resuming properly, a crashed prior run leaving plan steps open, concurrent Ask calls on the same checkpointed agent, or resetting memory/checkpoint without clearing plan state.

Related errors


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