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

  1. Inspect the wrapped cause to identify the OS-level problem
  2. Retry the read — transient I/O and race conditions often resolve
  3. For actively-written files, snapshot first (cp) and view the copy
  4. 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

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


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/40b55ad55e8b9ef8. Report an issue: GitHub.