charmbracelet/crush · error
failed to rename file: %w
Error message
failed to rename file: %w
What it means
applyDocumentChange wraps any failure from os.Rename(oldPath, newPath) when applying an LSP RenameFile change. os.Rename fails at the OS level (not because of policy like overwrite rules), so the wrapped error carries the syscall reason. The original error is preserved via %w.
Source
Thrown at internal/lsp/util/edit.go:231
oldPath, err = change.RenameFile.OldURI.Path()
if err != nil {
return err
}
newPath, err = change.RenameFile.NewURI.Path()
if err != nil {
return err
}
if change.RenameFile.Options != nil {
if !change.RenameFile.Options.Overwrite {
if _, err := os.Stat(newPath); err == nil {
return fmt.Errorf("target file already exists and overwrite is not allowed: %s", newPath)
}
}
}
if err := os.Rename(oldPath, newPath); err != nil {
return fmt.Errorf("failed to rename file: %w", err)
}
}
if change.TextDocumentEdit != nil {
textEdits := make([]protocol.TextEdit, len(change.TextDocumentEdit.Edits))
for i, edit := range change.TextDocumentEdit.Edits {
var err error
textEdits[i], err = edit.AsTextEdit()
if err != nil {
return fmt.Errorf("invalid edit type: %w", err)
}
}
return applyTextEdits(change.TextDocumentEdit.TextDocument.URI, textEdits, encoding)
}
return nil
}
View on GitHub (pinned to 7944b8e522)
Solutions
- Read the wrapped os error (os.IsNotExist, *fs.PathError) and verify both oldPath and newPath parent directory exist before calling ApplyWorkspaceEdit
- Create the destination directory first (os.MkdirAll)
- Ensure old and new paths are on the same filesystem, or fall back to copy+delete across devices
- Check process permissions on both paths
Example fix
// before
err := ApplyWorkspaceEdit(edit, enc)
// after
if err := os.MkdirAll(filepath.Dir(newPath), 0o755); err != nil {
return err
}
if _, err := os.Stat(oldPath); err != nil {
return fmt.Errorf("source missing: %w", err)
}
err = ApplyWorkspaceEdit(edit, enc) Defensive patterns
Strategy: validation
Validate before calling
func canRename(oldPath, newPath string) error {
if _, err := os.Stat(oldPath); err != nil {
return fmt.Errorf("source missing: %w", err)
}
if err := os.MkdirAll(filepath.Dir(newPath), 0o755); err != nil {
return err
}
if of, nf := filepath.Abs(oldPath), filepath.Abs(newPath); filepath.Dir(of) != filepath.Dir(nf) {
// warn: potential cross-device rename
}
return nil
} Try / catch
var pathErr *fs.PathError
if err := ApplyWorkspaceEdit(edit, enc); err != nil {
if errors.As(err, &pathErr) {
log.Printf("rename failed at %s: %v", pathErr.Path, pathErr.Err)
}
} Prevention
- Ensure the destination directory exists before applying rename edits
- Keep renames within one filesystem; implement copy+delete fallback for cross-device moves
- Check write permissions on source and destination directories
When it happens
Trigger: os.Rename fails: oldPath does not exist, paths span different mount points/filesystems (EXDEV), permission denied, or newPath's parent directory does not exist.
Common situations: Renaming into a directory that was deleted or never created; moving a file across filesystems (e.g. /tmp to a mounted volume); file locked/held by another process on Windows; running without write permission on the source or destination directory.
Related errors
- target file already exists and overwrite is not allowed: %s
- permission request failed: %w
- failed to read file: %w
- failed to create parent directories: %w
- failed to create output file: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/9692db18551c7569.
Report an issue: GitHub.