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

  1. Re-run the call; transient ENOENT races usually resolve once the concurrent deletion finishes.
  2. Check permissions on the apply files and the applies directory.
  3. Identify which file fails from the wrapped error path and remove/repair it if corrupt.
  4. 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

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


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/3d6bb8c9ab8de695. Report an issue: GitHub.