charmbracelet/crush · error

failed to delete directory recursively: %w

Error message

failed to delete directory recursively: %w

What it means

For a DeleteFile change with Options.Recursive set, applyDocumentChange calls os.RemoveAll; failure is wrapped with this message. It means a recursive directory deletion could not complete (permission, file in use, non-empty constraints imposed by the OS).

Source

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

				if _, err := os.Stat(path); err == nil {
					return nil // File exists and we're ignoring it
				}
			}
		}
		if err := os.WriteFile(path, []byte(""), 0o644); err != nil {
			return fmt.Errorf("failed to create file: %w", err)
		}
	}

	if change.DeleteFile != nil {
		path, err := change.DeleteFile.URI.Path()
		if err != nil {
			return fmt.Errorf("invalid URI: %w", err)
		}

		if change.DeleteFile.Options != nil && change.DeleteFile.Options.Recursive {
			if err := os.RemoveAll(path); err != nil {
				return fmt.Errorf("failed to delete directory recursively: %w", err)
			}
		} else {
			if err := os.Remove(path); err != nil {
				return fmt.Errorf("failed to delete file: %w", err)
			}
		}
	}

	if change.RenameFile != nil {
		var newPath, oldPath string
		var err error

		oldPath, err = change.RenameFile.OldURI.Path()
		if err != nil {
			return err
		}

		newPath, err = change.RenameFile.NewURI.Path()

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify write permission on the directory and all its contents.
  2. Close editors/processes holding handles to files inside the tree.
  3. Check for read-only mounts or immutable attributes.
  4. Fall back to manual deletion and inspect the wrapped OS error for the offending path.

Example fix

// before
// read-only files inside tree
util.ApplyWorkspaceEdit(ctx, delEdit)
// after
filepath.Walk(dir, func(p string, info os.FileInfo, err error) error {
    return os.Chmod(p, 0o755)
})
util.ApplyWorkspaceEdit(ctx, delEdit)
Defensive patterns

Strategy: try-catch

Validate before calling

if err := filepath.Walk(dir, func(p string, info os.FileInfo, err error) error {
    if err != nil { return err }
    return os.Chmod(p, 0o755)
}); err != nil {
    return err
}

Try / catch

var rmErr *fs.PathError
if errors.As(err, &rmErr) {
    log.Printf("recursive delete blocked at %s: %v", rmErr.Path, rmErr.Err)
}

Prevention

When it happens

Trigger: Recursive delete of a directory where any contained file/directory cannot be removed due to permissions, an open handle, or filesystem errors.

Common situations: Deleting directories containing read-only files; removing folders with files locked by another process or editor; sandbox restrictions blocking deletion.

Related errors


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