charmbracelet/crush · error
error reading file: %w
Error message
error reading file: %w
What it means
readTextFile failed while reading the text file content, and the error was not the handled contentTooLargeError (which returns a friendly size-limit message instead). The wrapped cause could be an I/O error, a read race on a file that changed, or a limit/offset seeking issue inside readTextFile.
Source
Thrown at internal/agent/tools/view.go:242
// it identifies a supported image format.
mimeType = sniffImageMimeType(imageData, mimeType)
return fantasy.NewImageResponse(imageData, mimeType), nil
}
// Read the file content
maxContentSize := MaxViewSize
if isSkillFile {
maxContentSize = 0
}
content, hasMore, err := readTextFile(filePath, params.Offset, params.Limit, maxContentSize)
if err != nil {
var tooLarge contentTooLargeError
if errors.As(err, &tooLarge) {
return fantasy.NewTextErrorResponse(fmt.Sprintf("Content section is too large (%d bytes). Maximum size is %d bytes",
tooLarge.Size, tooLarge.Max)), nil
}
return fantasy.ToolResponse{}, fmt.Errorf("error reading file: %w", err)
}
if !utf8.ValidString(content) {
return fantasy.NewTextErrorResponse("File content is not valid UTF-8"), nil
}
openInLSPs(ctx, lspManager, filePath)
waitForLSPDiagnostics(ctx, lspManager, filePath, 300*time.Millisecond)
output := "<file>\n"
output += addLineNumbers(content, params.Offset+1)
if hasMore {
output += fmt.Sprintf("\n\n(File has more lines. Use 'offset' parameter to read beyond line %d)",
params.Offset+len(strings.Split(content, "\n")))
}
output += "\n</file>\n"
output += getDiagnostics(filePath, lspManager)
filetracker.RecordRead(ctx, sessionID, filePath)
View on GitHub (pinned to 7944b8e522)
Solutions
- Inspect the wrapped cause to identify the OS-level problem
- Retry the read — transient I/O and race conditions often resolve
- For actively-written files, snapshot first (cp) and view the copy
- Check disk health / remount network shares if errors persist
Example fix
// before view /var/log/app.log // log rotated mid-read // after cp /var/log/app.log /tmp/app.log.snapshot && view /tmp/app.log.snapshot
Defensive patterns
Strategy: retry
Validate before calling
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("file %q unreadable: %w", path, err)
}
f.Close() Type guard
func readableFile(path string) bool {
f, err := os.Open(path)
if err != nil { return false }
f.Close()
return true
} Try / catch
var tooLarge contentTooLargeError
if !errors.As(err, &tooLarge) { // too-large is handled as a text response already
var pe *fs.PathError
if errors.As(err, &pe) {
// I/O problem: retry or snapshot the file and re-read
}
} Prevention
- Snapshot actively-written files (logs) before viewing them
- Retry transient I/O failures, especially on network mounts
- Check disk health if read errors recur on the same volume
- Use offset/limit within the file's actual size bounds
When it happens
Trigger: I/O errors mid-read (failing disk, dropped network mount); the file being truncated/replaced while reading; internal errors from the offset/limit reading logic other than the too-large sentinel.
Common situations: Log files being actively rotated/rewritten while viewed; removable or network media disconnecting; files on failing hardware; extremely large files hitting other reader constraints.
Related errors
- error reading image file: %w
- failed to generate HTML: %w
- failed to create parent directories: %w
- failed to create output file: %w
- failed to write file: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/40b55ad55e8b9ef8.
Report an issue: GitHub.