plandex-ai/plandex · error

failed to read file %s: %v

Error message

failed to read file %s: %v

What it means

For non-truncated files, getMapFileDetails performs a partial read for the map via getMapFileContent and wraps any failure with this message. It means the file's content (and its sha) could not be read from disk, so the map entry for this file cannot be produced.

Source

Thrown at app/cli/lib/context_shared.go:84

			totalMapSizeExceeded = true
			res.mapFilesSkippedAfterSizeLimit = append(res.mapFilesSkippedAfterSizeLimit, path)
			res.tokens = shared.GetBytesToTokensEstimate(size)
		} else if truncated {
			res.mapFilesTruncatedTooLarge = append(res.mapFilesTruncatedTooLarge, filePathWithSize{Path: path, Size: size})
		}
	}

	if totalMapSizeExceeded || !shared.HasFileMapSupport(path) || isImage {
		shaVal := sha256.Sum256([]byte(fmt.Sprintf("%d", res.tokens)))
		res.shaVal = hex.EncodeToString(shaVal[:])

		res.mapContent = ""
		res.size = 0
	} else {
		// partial read for the map
		contentRes, err := getMapFileContent(path)
		if err != nil {
			return mapFileDetails{}, fmt.Errorf("failed to read file %s: %v", path, err)
		}

		res.mapContent = contentRes.content
		res.shaVal = contentRes.shaVal

		if contentRes.truncated {
			res.mapFilesTruncatedTooLarge = append(res.mapFilesTruncatedTooLarge, filePathWithSize{Path: path, Size: shared.MaxContextMapSingleInputSize})
			res.size = shared.MaxContextMapSingleInputSize
			res.tokens = shared.GetBytesToTokensEstimate(shared.MaxContextMapSingleInputSize)
		} else {
			// do the actual token count if we didn't truncate
			res.tokens = shared.GetNumTokensEstimate(res.mapContent)
		}
	}

	return res, nil
}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the file exists and is readable by the current user (ls -l / chmod)
  2. Restore deleted files (git checkout -- <file>) and re-run
  3. Exclude unreadable files from the context paths

Example fix

// before
contentRes, err := getMapFileContent(path)
if err != nil {
    return mapFileDetails{}, fmt.Errorf("failed to read file %s: %v", path, err)
}
// after
contentRes, err := getMapFileContent(path)
if err != nil {
    if os.IsPermission(err) {
        fmt.Printf("skipping unreadable file %s\n", path)
        return mapFileDetails{}, nil
    }
    return mapFileDetails{}, fmt.Errorf("failed to read file %s: %w", path, err)
}
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

func isReadableRegularFile(path string) bool {
    info, err := os.Stat(path)
    if err != nil || !info.Mode().IsRegular() { return false }
    f, err := os.Open(path)
    if err != nil { return false }
    f.Close()
    return true
}

Try / catch

contentRes, err := getMapFileContent(path)
if err != nil {
    if os.IsPermission(err) {
        fmt.Printf("skipping unreadable file %s\n", path)
    } else {
        return fmt.Errorf("failed to read file %s: %w", path, err)
    }
}

Prevention

When it happens

Trigger: getMapFileContent(path) returns an error during map building — permission-denied reads, file deleted mid-operation, or I/O errors on large/binary files.

Common situations: Files with restrictive permissions (root-owned, chmod 000); files removed by git checkout/clean while the command runs; encrypted or filesystem-corrupted files.

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/65b77438975940bc. Report an issue: GitHub.