plandex-ai/plandex · error

failed to read file %s: %v

Error message

failed to read file %s: %v

What it means

In the per-file goroutine of AutoLoadContextFiles, os.ReadFile fails after the stat check succeeded, meaning the file became unreadable between stat and read or lacks read permission. The error is sent to errCh and surfaces to the caller as "failed to load context".

Source

Thrown at app/cli/lib/context_auto_load.go:81

				log.Println("Skipping file", path, "because it's too large", size)
				filesSkippedTooLarge = append(filesSkippedTooLarge, filePathWithSize{Path: path, Size: size})
				mu.Unlock()
				errCh <- nil
				return
			}
			if totalSize+size > shared.MaxTotalContextSize {
				log.Println("Skipping file", path, "because it would exceed the max context body size", totalSize+size)
				filesSkippedAfterSizeLimit = append(filesSkippedAfterSizeLimit, path)
				mu.Unlock()
				errCh <- nil
				return
			}
			totalSize += size
			mu.Unlock()

			b, err := os.ReadFile(path)
			if err != nil {
				errCh <- fmt.Errorf("failed to read file %s: %v", path, err)
				return
			}

			var contextType shared.ContextType
			isImage := shared.IsImageFile(path)
			if isImage {
				contextType = shared.ContextImageType
			} else {
				contextType = shared.ContextFileType
			}

			var imageDetail openai.ImageURLDetail
			if isImage {
				imageDetail = openai.ImageURLDetailHigh
			}

			var body string
			if isImage {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the file's read permission bits (chmod or run as a user with access).
  2. Exclude special files: verify mode.Type() == 0 (regular file) after stat, not just !IsDir().
  3. Handle read races on rotated/deleted files by retrying once or skipping with a warning.
  4. Ensure the file is closed/unlocked by the writer (e.g. editor swap files, active log rotation) before loading.
  5. For network mounts, verify mount health and retry.

Example fix

// before
if fileInfo.IsDir() { ... }
b, err := os.ReadFile(path)
// after
if !fileInfo.Mode().IsRegular() {
    errCh <- nil // skip dirs, devices, fifos, sockets
    return
}
b, err := os.ReadFile(path)
if os.IsPermission(err) {
    log.Printf("skipping unreadable file %s: %v", path, err)
    errCh <- nil
    return
}
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil {
    return fmt.Errorf("bad path %s: %w", path, err)
}
if !info.Mode().IsRegular() {
    return fmt.Errorf("%s is not a regular file", path)
}
if f, err := os.Open(path); err != nil {
    return fmt.Errorf("%s not readable: %w", path, err)
} else { f.Close() }

Try / catch

b, err := os.ReadFile(path)
if err != nil {
    switch {
    case os.IsPermission(err):
        log.Printf("skipping unreadable file %s", path)
        errCh <- nil
    case os.IsNotExist(err):
        log.Printf("file vanished during load: %s", path)
        errCh <- nil
    default:
        errCh <- fmt.Errorf("failed to read file %s: %v", path, err)
    }
    return
}

Prevention

When it happens

Trigger: os.ReadFile(path) errors: permission denied (file mode or ACL), the file was truncated/rotated/deleted mid-run (race), the "file" is a device/FIFO or /proc-like special file that cannot be read conventionally, or I/O errors (bad sector, network mount drop).

Common situations: Loading log files being actively rotated, reading files owned by another user (e.g. root-only configs), pointing context loading at virtual filesystems (/proc, /sys) or sockets, or NFS/network mounts flaking.

Related errors


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