plandex-ai/plandex · error

error reading file: %v

Error message

error reading file: %v

What it means

In the file_map CLI, each filtered path is read with os.ReadFile in a goroutine. If the read fails (file missing, permission denied, is a directory, etc.) the goroutine pushes an 'error reading file: %v' wrapping the os error onto the error channel instead of mapping the file. It is a pass-through of the underlying OS I/O failure.

Source

Thrown at app/server/syntax/file_map/cli/main.go:52

	paths := args

	var filteredPaths []string
	for _, path := range paths {
		if shared.HasFileMapSupport(path) {
			filteredPaths = append(filteredPaths, path)
		}
	}

	errCh := make(chan error, len(filteredPaths))
	fileInputs := map[string]string{}
	var mu sync.Mutex

	for _, path := range filteredPaths {
		go func(path string) {
			content, err := os.ReadFile(path)
			if err != nil {
				errCh <- fmt.Errorf("error reading file: %v", err)
				return
			}
			mu.Lock()
			fileInputs[path] = string(content)
			mu.Unlock()
			errCh <- nil
		}(path)
	}

	for i := 0; i < len(filteredPaths); i++ {
		err := <-errCh
		if err != nil {
			fmt.Printf("error reading file: %v\n", err)
			os.Exit(1)
		}
	}

	if parserTree {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Verify each path exists and is a regular file (os.Stat) before/while filtering
  2. Check file permissions for the user running the CLI
  3. Re-run after refreshing the path list if files changed concurrently
  4. Wrap paths in absolute form relative to the intended working directory

Example fix

// before
filteredPaths, _ := collectPaths(root)
runMap(filteredPaths)
// after
for _, p := range filteredPaths {
    if fi, err := os.Stat(p); err != nil || fi.IsDir() {
        log.Printf("skipping unreadable path %s: %v", p, err)
        continue
    }
}
runMap(filteredPaths)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil || info.IsDir() {
    return fmt.Errorf("skip %s: %v", path, err)
}
if file, err := os.Open(path); err != nil {
    return fmt.Errorf("unreadable %s: %v", path, err)
} else { file.Close() }

Type guard

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

Try / catch

if err := runCLI(paths); err != nil && strings.HasPrefix(err.Error(), "error reading file:") {
    log.Printf("file access problem: %v — check path/permissions", err)
}

Prevention

When it happens

Trigger: Running the file_map CLI on paths that don't exist, aren't readable by the current user, are directories rather than files, or that were deleted between path filtering and reading (race with filesystem changes).

Common situations: Typo'd or stale file list, running the tool as a user lacking read permissions, reading symlink targets that point nowhere, reading directories not pruned by the filter step.

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


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