plandex-ai/plandex · error

failed to get file info for %s: %v

Error message

failed to get file info for %s: %v

What it means

Emitted from the per-file goroutine in MustLoadContext when os.Stat(path) fails while gathering file size before loading. After paths were successfully enumerated and ignore-filtered, the file could not be stat'ed — meaning it was deleted or renamed between enumeration and stat, or is inaccessible due to permissions. The error is sent on errCh and the file is skipped.

Source

Thrown at app/cli/lib/context_load.go:457

					if !params.DefsOnly {
						composite := strings.Join([]string{string(contextType), path}, "|")
						if existsByComposite[composite] != nil {
							alreadyLoadedByComposite[composite] = existsByComposite[composite]
							continue
						}
					}

					numRoutines++

					go func(path string) {
						sem <- struct{}{}
						defer func() { <-sem }()

						var size int64

						fileInfo, err := os.Stat(path)
						if err != nil {
							errCh <- fmt.Errorf("failed to get file info for %s: %v", path, err)
							return
						}
						size = fileInfo.Size()

						if !params.DefsOnly && size > shared.MaxContextBodySize {
							contextMu.Lock()
							filesSkippedTooLarge = append(filesSkippedTooLarge, filePathWithSize{Path: path, Size: size})
							contextMu.Unlock()
							errCh <- nil
							return
						}

						if !params.DefsOnly {
							contextMu.Lock()
							if totalSize+size > shared.MaxContextBodySize {
								filesSkippedAfterSizeLimit = append(filesSkippedAfterSizeLimit, path)
								contextMu.Unlock()
								errCh <- nil

View on GitHub (pinned to e2d772072e)

Solutions

  1. Re-run the load once the working tree is static; enumeration-to-stat races vanish on a stable tree.
  2. Check the wrapped os error: ENOENT -> file vanished, EACCES -> fix permissions (chmod/chown or run with adequate rights).
  3. Verify symlinks in the target paths are not broken (ls -L / readlink).
  4. Stop concurrent processes (codegen, tests, git hooks) that delete or rename files while loading.

Example fix

// before: file deleted between scan and stat
$ plandex load ./dist
// error: failed to get file info for ./dist/app.js: stat ./dist/app.js: no such file or directory
// after: rebuild/generate first so the tree is complete, then load
$ npm run build && plandex load ./dist
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check every path is stat-able before loading
for _, p := range inputPaths {
    if _, err := os.Stat(p); err != nil {
        return fmt.Errorf("cannot stat %s before load: %w", p, err)
    }
}

Type guard

func fileAccessible(path string) bool {
    info, err := os.Stat(path)
    return err == nil && info.Mode().IsRegular()
}

Try / catch

if err := loadContextErr; err != nil {
    var statErr *fs.PathError
    if strings.Contains(err.Error(), "failed to get file info for") {
        // file vanished or unreadable between enumeration and stat
        log.Printf("skipping load, tree changed or unreadable: %v", err)
        // regenerate/rebuild outputs, fix permissions, then retry once
        return retryLoad(inputPaths)
    }
    return err
}

Prevention

When it happens

Trigger: os.Stat returns an error such as ENOENT (file deleted/renamed after enumeration), EACCES (permission denied on file or parent dir), or a broken symlink being stat'ed.

Common situations: Concurrent builds/clean tasks removing generated files during load; files removed by git operations mid-run; unreadable files due to restrictive permissions or root-owned artifacts; TOCTOU races in large repos.

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/0d6d71b847f0e5c6. Report an issue: GitHub.