{"record":{"id":"e2a97ec5c6c9d1db","repo":"charmbracelet/crush","slug":"failed-to-read-file-w-e2a97e","errorCode":null,"errorMessage":"failed to read file: %w","messagePattern":"failed to read file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lsp/util/edit.go","lineNumber":23,"sourceCode":"\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\tpowernap \"github.com/charmbracelet/x/powernap/pkg/lsp\"\n\t\"github.com/charmbracelet/x/powernap/pkg/lsp/protocol\"\n)\n\nfunc applyTextEdits(uri protocol.DocumentURI, edits []protocol.TextEdit, encoding powernap.OffsetEncoding) error {\n\tpath, err := uri.Path()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid URI: %w\", err)\n\t}\n\n\t// Read the file content\n\tcontent, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read file: %w\", err)\n\t}\n\n\t// Detect line ending style\n\tvar lineEnding string\n\tif bytes.Contains(content, []byte(\"\\r\\n\")) {\n\t\tlineEnding = \"\\r\\n\"\n\t} else {\n\t\tlineEnding = \"\\n\"\n\t}\n\n\t// Track if file ends with a newline\n\tendsWithNewline := len(content) > 0 && bytes.HasSuffix(content, []byte(lineEnding))\n\n\t// Split into lines without the endings\n\tlines := strings.Split(string(content), lineEnding)\n\n\t// Check for overlapping edits\n\tfor i, edit1 := range edits {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/lsp/util/edit.go#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the file exists at the path encoded in the URI before applying the edit (os.Stat).","Check file read permissions for the user running the process.","Regenerate the workspace edit from a fresh document snapshot so URIs are current.","If the file should be newly created, send a CreateFile change instead of a TextDocumentEdit."],"exampleFix":"// before\n// blind apply\nerr := util.ApplyWorkspaceEdit(ctx, edit)\n// after\nif _, statErr := os.Stat(path); statErr != nil {\n    return fmt.Errorf(\"file missing before edit: %w\", statErr)\n}\nerr := util.ApplyWorkspaceEdit(ctx, edit)","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(path); err != nil || info.IsDir() {\n    return fmt.Errorf(\"cannot apply edit: %s is not a readable file\", path)\n}","typeGuard":null,"tryCatchPattern":"var readErr *fs.PathError\nif errors.As(err, &readErr) && errors.Is(readErr, fs.ErrNotExist) {\n    // recreate or refresh document before retrying\n}","preventionTips":["Stat the file before constructing TextDocumentEdits.","Refresh document URIs after any external git/file operation.","Run the LSP client with sufficient filesystem permissions."],"tags":["lsp","file-io","workspace-edit"],"backgroundTag":"file-read-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}