plandex-ai/plandex · error
failed to read the file %s: %v
Error message
failed to read the file %s: %v
What it means
During the outdated check, each file-type context is read concurrently with os.ReadFile to hash/compare against stored state. If a file that passed the initial os.Stat existence check cannot be read (permission, race with deletion, I/O error), the error is collected into the errs list with the file path.
Source
Thrown at app/cli/lib/context_update.go:388
defer wg.Done()
sem <- struct{}{}
defer func() { <-sem }()
if _, err := os.Stat(ctx.FilePath); os.IsNotExist(err) {
mu.Lock()
defer mu.Unlock()
deleteIds[ctx.Id] = true
numFilesRemoved++
tokenDiffsById[ctx.Id] = -ctx.NumTokens
return
}
fileContent, err := os.ReadFile(ctx.FilePath)
if err != nil {
mu.Lock()
defer mu.Unlock()
errs = append(errs, fmt.Errorf("failed to read the file %s: %v", ctx.FilePath, err))
return
}
fileContent = shared.NormalizeEOL(fileContent)
fileInfo, err := os.Stat(ctx.FilePath)
if err != nil {
mu.Lock()
defer mu.Unlock()
errs = append(errs, fmt.Errorf("failed to get file info for %s: %v", ctx.FilePath, err))
return
}
size := fileInfo.Size()
// Individual skip checks
if size > shared.MaxContextBodySize {
mu.Lock()
defer mu.Unlock()
View on GitHub (pinned to e2d772072e)
Solutions
- Fix permissions on the reported file (chmod/chown) or run as a user with read access
- If the file no longer exists, remove it from context (plandex context rm) and re-add
- Re-run the command — race-related failures usually clear
- Check the filesystem/mount health if errors persist across many files
Example fix
// before: ignoring collected errs
outdated, err := lib.CheckOutdatedContext(nil, paths)
// after: ensure all context files are readable before checking
for _, c := range contexts {
if c.ContextType == shared.ContextFileType {
if f, err := os.Open(c.FilePath); err != nil {
log.Fatalf("cannot read context file %s: %v", c.FilePath, err)
} else { f.Close() }
}
}
outdated, err := lib.CheckOutdatedContext(contexts, paths) Defensive patterns
Strategy: validation
Validate before calling
for _, c := range contexts {
if c.ContextType == shared.ContextFileType {
f, err := os.Open(c.FilePath)
if err != nil {
return fmt.Errorf("pre-flight: cannot open %s: %w", c.FilePath, err)
}
f.Close()
}
} Try / catch
outdated, err := lib.CheckOutdatedContext(contexts, paths)
if err != nil {
if strings.Contains(err.Error(), "failed to read the file ") {
// extract path, drop it from context or fix perms, then retry
return fmt.Errorf("fix unreadable context file, then re-run: %w", err)
}
return err
} Prevention
- Check file readability before adding files to context
- Avoid deleting/moving files while commands run
- Run CLI and file owner under the same user in CI
- Watch for TOCTOU: stat-then-read races on actively edited files
When it happens
Trigger: os.ReadFile(ctx.FilePath) fails after os.Stat succeeded: permission denied on the file, file deleted between stat and read (TOCTOU race), read-only filesystem, or file is a special device/pipe that cannot be read normally.
Common situations: CI running as a different user than the one who added context; files on a network mount that dropped; editor/tooling swapping files (atomic rename) mid-check; chmod changes after adding files to context.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- error deleting result file: %v
- error walking directory: %s
- failed to check if %s exists: %s
- failed to read %s: %s
- failed to write %s: %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/e729f4fb4abc75f3.
Report an issue: GitHub.