{"record":{"id":"dabf7784bd18edd1","repo":"plandex-ai/plandex","slug":"plan-updates-out-of-order-s","errorCode":null,"errorMessage":"plan updates out of order: %s","messagePattern":"plan updates out of order: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/shared/plan_result_replacements.go","lineNumber":190,"sourceCode":"\t\t\t}\n\n\t\t\tif planRes.RemovedFile {\n\t\t\t\tupdated = \"\"\n\t\t\t\tdelete(files, path)\n\t\t\t\tdelete(shas, path)\n\t\t\t\tdelete(updatedAtByPath, path)\n\t\t\t\tremovedByPath[path] = true\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif len(planRes.Replacements) == 0 {\n\t\t\t\tif updated != \"\" {\n\t\t\t\t\tlog.Println(\"plan updates out of order:\", path)\n\t\t\t\t\tlog.Println(\"updated:\")\n\t\t\t\t\tlog.Println(updated)\n\t\t\t\t\tlog.Println(\"planRes.Content:\")\n\t\t\t\t\tlog.Println(planRes.Content)\n\t\t\t\t\treturn nil, fmt.Errorf(\"plan updates out of order: %s\", path)\n\t\t\t\t}\n\n\t\t\t\tupdated = planRes.Content\n\t\t\t\tfiles[path] = updated\n\t\t\t\tupdatedAtByPath[path] = planRes.CreatedAt\n\t\t\t\tdelete(removedByPath, path)\n\n\t\t\t\tcontinue\n\t\t\t} else if updated == \"\" {\n\t\t\t\tcontext := planState.ContextsByPath[path]\n\n\t\t\t\tif context == nil {\n\t\t\t\t\t// spew.Dump(planRes)\n\n\t\t\t\t\treturn nil, fmt.Errorf(\"no context for path: %s\", path)\n\t\t\t\t}\n\n\t\t\t\t// log.Println(\"No updated content -- setting to context body\")","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/shared/plan_result_replacements.go#L172-L208","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfiles := GetFiles(planResults)\n// after\nsort.Slice(planResults, func(i, j int) bool { return planResults[i].CreatedAt.Before(planResults[j].CreatedAt) })\nfiles := GetFiles(planResults)","handlingStrategy":"validation","validationCode":"func ensureOrdered(results []shared.PlanResult) error {\n    seen := map[string]time.Time{}\n    for _, r := range results {\n        if t, ok := seen[r.Path]; ok && r.CreatedAt.Before(t) {\n            return fmt.Errorf(\"out-of-order result for %s\", r.Path)\n        }\n        seen[r.Path] = r.CreatedAt\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"files, err := GetFiles(results, state)\nif err != nil {\n    if strings.Contains(err.Error(), \"plan updates out of order\") {\n        path := extractPath(err.Error())\n        results = filterLatestPerPath(results, path)\n        files, err = GetFiles(results, state)\n    }\n    if err != nil { return err }\n}","preventionTips":["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"],"tags":["go","ordering","plan-results","state"],"backgroundTag":"updates-out-of-order","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}