plandex-ai/plandex · error
plan updates out of order: %s
Error message
plan updates out of order: %s
What it means
While assembling files from ordered plan results, GetFilesBeforeReplacement detected a second (later) update for a path when content for that path had already been recorded and then the ordering check found non-empty prior content at an unexpected position — i.e. plan results for the same file arrive out of chronological order. The library fails fast because applying out-of-order updates would produce wrong file content.
Source
Thrown at app/shared/plan_result_replacements.go:190
}
if planRes.RemovedFile {
updated = ""
delete(files, path)
delete(shas, path)
delete(updatedAtByPath, path)
removedByPath[path] = true
continue
}
if len(planRes.Replacements) == 0 {
if updated != "" {
log.Println("plan updates out of order:", path)
log.Println("updated:")
log.Println(updated)
log.Println("planRes.Content:")
log.Println(planRes.Content)
return nil, fmt.Errorf("plan updates out of order: %s", path)
}
updated = planRes.Content
files[path] = updated
updatedAtByPath[path] = planRes.CreatedAt
delete(removedByPath, path)
continue
} else if updated == "" {
context := planState.ContextsByPath[path]
if context == nil {
// spew.Dump(planRes)
return nil, fmt.Errorf("no context for path: %s", path)
}
// log.Println("No updated content -- setting to context body")View on GitHub (pinned to e2d772072e)
Solutions
- Ensure plan results are sorted by CreatedAt before calling GetFiles
- Deduplicate plan results per path, keeping only the latest entry
- Audit the writer that produced the out-of-order results (retries/concurrency) and serialize writes per path
- Use the logged `updated` vs `planRes.Content` output to identify the offending result and delete/repair it
Example fix
// before
files := GetFiles(planResults)
// after
sort.Slice(planResults, func(i, j int) bool { return planResults[i].CreatedAt.Before(planResults[j].CreatedAt) })
files := GetFiles(planResults) Defensive patterns
Strategy: validation
Validate before calling
func ensureOrdered(results []shared.PlanResult) error {
seen := map[string]time.Time{}
for _, r := range results {
if t, ok := seen[r.Path]; ok && r.CreatedAt.Before(t) {
return fmt.Errorf("out-of-order result for %s", r.Path)
}
seen[r.Path] = r.CreatedAt
}
return nil
} Try / catch
files, err := GetFiles(results, state)
if err != nil {
if strings.Contains(err.Error(), "plan updates out of order") {
path := extractPath(err.Error())
results = filterLatestPerPath(results, path)
files, err = GetFiles(results, state)
}
if err != nil { return err }
} Prevention
- Sort plan results by CreatedAt before calling GetFiles
- Deduplicate per-path results keeping only the latest
- Serialize per-path plan writes to avoid concurrent reordering
When it happens
Trigger: Calling GetFiles (which delegates to GetFilesBeforeReplacement) with a plan result list where a path's update content appears again after it was already set, with the logged `updated` differing from the current planRes.Content ordering assumptions — i.e. duplicate or reordered updates for the same path.
Common situations: Plan result storage or streaming that got replayed/reordered (retries, concurrent writers, manual DB edits); multiple plan runs writing the same file with stale results interleaved.
Related errors
- no context for path: %s
- no current project
- no current plan
- active plan not found for plan ID %s and branch %s
- active plan not found for plan ID %s and branch %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/dabf7784bd18edd1.
Report an issue: GitHub.