charmbracelet/crush · error

failed to read file: %w

Error message

failed to read file: %w

What it means

applyTextEdits reads the target file from disk before applying LSP text edits. When os.ReadFile fails (missing file, permission denied, path is a directory), the OS error is wrapped with this message. It indicates the workspace edit referenced a document whose on-disk state is unreadable.

Source

Thrown at internal/lsp/util/edit.go:23

	"fmt"
	"os"
	"sort"
	"strings"

	powernap "github.com/charmbracelet/x/powernap/pkg/lsp"
	"github.com/charmbracelet/x/powernap/pkg/lsp/protocol"
)

func applyTextEdits(uri protocol.DocumentURI, edits []protocol.TextEdit, encoding powernap.OffsetEncoding) error {
	path, err := uri.Path()
	if err != nil {
		return fmt.Errorf("invalid URI: %w", err)
	}

	// Read the file content
	content, err := os.ReadFile(path)
	if err != nil {
		return fmt.Errorf("failed to read file: %w", err)
	}

	// Detect line ending style
	var lineEnding string
	if bytes.Contains(content, []byte("\r\n")) {
		lineEnding = "\r\n"
	} else {
		lineEnding = "\n"
	}

	// Track if file ends with a newline
	endsWithNewline := len(content) > 0 && bytes.HasSuffix(content, []byte(lineEnding))

	// Split into lines without the endings
	lines := strings.Split(string(content), lineEnding)

	// Check for overlapping edits
	for i, edit1 := range edits {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify the file exists at the path encoded in the URI before applying the edit (os.Stat).
  2. Check file read permissions for the user running the process.
  3. Regenerate the workspace edit from a fresh document snapshot so URIs are current.
  4. If the file should be newly created, send a CreateFile change instead of a TextDocumentEdit.

Example fix

// before
// blind apply
err := util.ApplyWorkspaceEdit(ctx, edit)
// after
if _, statErr := os.Stat(path); statErr != nil {
    return fmt.Errorf("file missing before edit: %w", statErr)
}
err := util.ApplyWorkspaceEdit(ctx, edit)
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(path); err != nil || info.IsDir() {
    return fmt.Errorf("cannot apply edit: %s is not a readable file", path)
}

Try / catch

var readErr *fs.PathError
if errors.As(err, &readErr) && errors.Is(readErr, fs.ErrNotExist) {
    // recreate or refresh document before retrying
}

Prevention

When it happens

Trigger: Calling ApplyWorkspaceEdit/applyDocumentChange with a TextDocumentEdit whose URI resolves to a path that does not exist, lacks read permission, or points to a directory instead of a regular file.

Common situations: File was deleted or moved by an external tool between edit generation and application; stale URI after a git operation; running the process as a user without read access to the file.

Related errors


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