sipeed/picoclaw · error
✗ failed to install skill: %w
Error message
✗ failed to install skill: %w
What it means
registry.DownloadAndInstall failed — the download, archive fetch, or extraction errored within the hard-coded 60-second context. The partial target directory is automatically removed and the underlying error is wrapped, so the wrapped text distinguishes network, HTTP, and extraction failures.
Source
Thrown at cmd/picoclaw/internal/skills/helpers.go:91
if _, err = os.Stat(targetDir); err == nil {
return fmt.Errorf("\u2717 skill '%s' already installed at %s", dirName, targetDir)
}
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
if err = os.MkdirAll(filepath.Join(workspace, "skills"), 0o755); err != nil {
return fmt.Errorf("\u2717 failed to create skills directory: %w", err)
}
result, err := registry.DownloadAndInstall(ctx, target, "", targetDir)
if err != nil {
rmErr := os.RemoveAll(targetDir)
if rmErr != nil {
fmt.Printf("\u2717 Failed to remove partial install: %v\n", rmErr)
}
return fmt.Errorf("✗ failed to install skill: %w", err)
}
if result.IsMalwareBlocked {
rmErr := os.RemoveAll(targetDir)
if rmErr != nil {
fmt.Printf("\u2717 Failed to remove partial install: %v\n", rmErr)
}
return fmt.Errorf("\u2717 Skill '%s' is flagged as malicious and cannot be installed.\n", target)
}
if result.IsSuspicious {
fmt.Printf("\u26a0\ufe0f Warning: skill '%s' is flagged as suspicious.\n", target)
}
if !workspaceHasValidSkillDirectory(workspace, dirName) {
_ = os.RemoveAll(targetDir)
return fmt.Errorf("✗ failed to install skill: registry archive for %q is not a valid skill", target)View on GitHub (pinned to 49183d7e8d)
Solutions
- Read the wrapped cause — it separates timeout vs HTTP error vs extraction failure.
- Retry once or twice with backoff; transient registry/network errors dominate.
- Verify the target exists on the registry's site.
- For large skills on slow links, note the 60s timeout is fixed in code — retry on a faster network or raise the constant locally.
Defensive patterns
Strategy: retry
Try / catch
result, err := registry.DownloadAndInstall(ctx, target, "", targetDir)
if err != nil {
// helper already removed the partial dir; safe to retry idempotently
if ctx.Err() == context.DeadlineExceeded || isRetryable(err) {
return retryWithBackoff()
}
return fmt.Errorf("failed to install skill: %w", err)
} Prevention
- Retry installs once after backoff before reporting failure.
- Account for the 60s download deadline when timing automation.
- Pin known-good versions to avoid not-found paths.
When it happens
Trigger: A network failure or the 60s context deadline expiring while downloading the archive, the registry returning an error for the target, or a corrupt/unreadable archive — helpers.go:91 (the helper RemoveAlls the partial install on this path).
Common situations: Slow link exceeding the fixed 60s deadline, registry rate-limiting or downtime, target not published at the requested version, or an upstream git host outage for git-backed registries.
Related errors
- request failed: %w
- ✗ invalid install target %q: %w
- ✗ Skill '%s' is flagged as malicious and cannot be installed
- ✗ failed to install skill: registry archive for %q is not a
- failed to send request: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/c8fdcb94eb7d517c.
Report an issue: GitHub.