plandex-ai/plandex · error
error reading apply file: %v
Error message
error reading apply file: %v
What it means
Inside GetPlanApplies' per-file goroutine, os.ReadFile of an individual apply file failed; the error is sent on errCh and later wrapped as "error getting plan applies". A file can disappear between ReadDir and ReadFile, or be unreadable due to permissions or I/O errors.
Source
Thrown at app/server/db/result_helpers.go:1058
planApplies := []*PlanApply{}
var mu sync.Mutex
errCh := make(chan error, len(files))
for _, file := range files {
go func(file os.DirEntry) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in GetPlanApplies: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("panic in GetPlanApplies: %v\n%s", r, debug.Stack())
runtime.Goexit() // don't allow outer function to continue and double-send to channel
}
}()
bytes, err := os.ReadFile(filepath.Join(appliesDir, file.Name()))
if err != nil {
errCh <- fmt.Errorf("error reading apply file: %v", err)
return
}
var apply PlanApply
err = json.Unmarshal(bytes, &apply)
if err != nil {
errCh <- fmt.Errorf("error unmarshalling apply file: %v", err)
return
}
mu.Lock()
planApplies = append(planApplies, &apply)
mu.Unlock()
errCh <- nil
}(file)
}View on GitHub (pinned to e2d772072e)
Solutions
- Re-run the call; transient ENOENT races usually resolve once the concurrent deletion finishes.
- Check permissions on the apply files and the applies directory.
- Identify which file fails from the wrapped error path and remove/repair it if corrupt.
- Avoid external processes touching the plan data directory while the server runs.
Defensive patterns
Strategy: retry
Try / catch
var applies []*db.PlanApply
var err error
for i := 0; i < 3; i++ {
applies, err = GetPlanApplies(orgId, planId)
if err == nil || !strings.Contains(err.Error(), "error reading apply file") {
break
}
time.Sleep(100 * time.Millisecond) // transient ENOENT race from concurrent deletion
} Prevention
- Don't run external cleanup/deletion scripts against the applies dir while the server is serving reads.
- Make deletes of apply files atomic (rename to trash dir first) to shrink the race window.
- Check permissions on apply files after any data migration.
When it happens
Trigger: An apply JSON file in the applies directory was deleted/renamed concurrently (race between listing and reading), is a directory itself, or is unreadable by the server process.
Common situations: Concurrent cleanup or plan deletion while another request lists applies; tmp/partial files written by another process; permission drift on the data dir.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- error reading convo file: %v
- error loading accounts: %v
- no project root found
- error getting git root: %s
- error getting files in git repo: %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/3d6bb8c9ab8de695.
Report an issue: GitHub.