sipeed/picoclaw · error
failed to remove skill '%s': %w
Error message
failed to remove skill '%s': %w
What it means
os.RemoveAll on <workspace>/skills/<name> returned a non-nil error, wrapped with the skill name and the underlying cause. This is an OS-level failure during deletion (permissions, read-only filesystem, open file handles), not a validation problem — the directory existed but could not be removed.
Source
Thrown at cmd/picoclaw/internal/skills/helpers.go:177
if name == "" {
return fmt.Errorf("skill name is required")
}
if strings.Contains(name, "/") {
dirName, err := skills.GitHubInstallDirNameFromToolsConfig(toolsConfig, name)
if err != nil || dirName == "" {
return fmt.Errorf("invalid skill name %q", skillName)
}
name = dirName
}
if name == "." || name == ".." {
return fmt.Errorf("invalid skill name %q", skillName)
}
skillDir := filepath.Join(workspace, "skills", name)
if _, err := os.Stat(skillDir); os.IsNotExist(err) {
return fmt.Errorf("skill '%s' not found", name)
}
if err := os.RemoveAll(skillDir); err != nil {
return fmt.Errorf("failed to remove skill '%s': %w", name, err)
}
return nil
}
func skillsInstallBuiltinCmd(workspace string) {
builtinSkillsDir := "./picoclaw/skills"
workspaceSkillsDir := filepath.Join(workspace, "skills")
fmt.Printf("Copying builtin skills to workspace...\n")
skillsToInstall := []string{
"weather",
"news",
"stock",
"calculator",
}
for _, skillName := range skillsToInstall {View on GitHub (pinned to 49183d7e8d)
Solutions
- Inspect the wrapped %w cause: EACCES/EPERM means permissions, EROFS means read-only mount
- Fix ownership/permissions on the skill directory (e.g. chown -R or chmod -R u+w <workspace>/skills/<name>) and retry
- Close editors/IDEs/indexers that may hold files inside the skill directory, then retry
- On Windows, retry after stopping antivirus/indexing locks or reboot if a handle is stuck
Example fix
# inspect the cause picoclaw skills remove weather # -> failed to remove skill 'weather': ... permission denied # fix and retry chmod -R u+w ~/.picoclaw/skills/weather && picoclaw skills remove weather
Defensive patterns
Strategy: retry
Validate before calling
func canRemove(dir string) bool {
info, err := os.Stat(dir)
return err == nil && info.IsDir() && info.Mode().Perm()&0200 != 0
} Try / catch
err := skillsRemoveFromWorkspace(ws, cfg, name)
if err != nil {
if strings.Contains(err.Error(), "failed to remove skill") {
// inspect errors.Unwrap(err) for EACCES/EROFS; remediate perms or close locks, then retry once
}
} Prevention
- Run the CLI as the user who owns the workspace
- Keep workspace skills on a writable local filesystem
- Close editors/watchers that lock files inside skill directories
When it happens
Trigger: Removing a skill whose directory contains files the process cannot write/delete (ownership mismatch, mode bits), a read-only or full disk mount, or (on Windows) a file inside the skill dir held open by an editor, indexer, or antivirus.
Common situations: Workspace created by root/admin but CLI run as a normal user; workspace on a network or read-only mount; a file watcher or IDE holding SKILL.md open; NFS stale-handle errors.
Related errors
- failed to save config: %w
- failed to stat local command %q: %w
- local command %q is not executable
- skill '%s' not found
- create output dir: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/1522709601aa6328.
Report an issue: GitHub.