micro/go-micro · error

run %s not found

Error message

run %s not found

What it means

Resume loads the run record for the given runID from the checkpoint store. The store returns ok=false when no run with that ID exists; the library translates this into a 'run not found' error rather than silently succeeding. This distinguishes 'checkpoint store reachable but ID unknown' from store errors.

Source

Thrown at flow/steps.go:429

// Resume continues a persisted run by id, picking up at the step it
// stopped on. Completed runs are a no-op.
func (f *Flow) Resume(ctx context.Context, runID 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 == "done" {
		return nil
	}
	_, err = f.runFrom(ctx, run)
	return err
}

// ResumePending resumes every checkpointed run for this flow that has not
// completed yet, in the same oldest-first order returned by Pending.
//
// It is a convenience for service startup and recovery loops: after a process
// restart, call ResumePending to drain the durable backlog without having to
// list and resume each run manually. If any run fails again, ResumePending
// stops and returns that run id with the error so callers can log, alert, or
// retry later without hiding the failing run.
func (f *Flow) ResumePending(ctx context.Context) (string, error) {
	ctx, cancel := f.withTimeout(ctx)

View on GitHub (pinned to 24529f1404)

Solutions

  1. Verify the runID exists: list runs via ResumePending or query the checkpoint store directly before resuming.
  2. Point the flow's Checkpoint at the same persistent store the run was originally saved to (check store address/bucket/prefix).
  3. Use a durable store (file/db backed) instead of an in-memory one if runs must survive process restarts.
  4. Confirm the run wasn't deleted by DeleteOnSuccess after it completed; if status was 'done', Resume would have been a no-op anyway.

Example fix

// before
err := f.Resume(ctx, runIDFromMemory)

// after
run, ok, err := store.Read(ctx, runID) // or check ResumePending output
if !ok {
  return fmt.Errorf("run %s is not in this checkpoint store", runID)
}
err = f.Resume(ctx, runID)
Defensive patterns

Strategy: validation

Validate before calling

runs, err := f.ResumePending(ctx) // or query the store
// verify runID appears in the pending set before resuming
found := slices.ContainsFunc(runs, func(r flow.Run) bool { return r.ID == runID })
if !found {
    return fmt.Errorf("run %s not present in checkpoint store", runID)
}

Try / catch

if err := f.Resume(ctx, runID); err != nil {
    var nfErr *notFoundError // or match on message
    if strings.Contains(err.Error(), "not found") {
        // look up correct runID or skip
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling flow.Resume(ctx, runID) with a runID that was never persisted, was already deleted (e.g. DeleteOnSuccess removed it after completion), or belongs to a different checkpoint store/prefix than the one this Flow uses.

Common situations: Restarting a service pointed at a different or emptied store (in-memory store lost on restart); typo'd or stale runID from an old log; run already finished and cleaned up due to DeleteOnSuccess; resuming a run created by a flow with a different name so the key doesn't match.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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