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

  1. Read the wrapped cause — it separates timeout vs HTTP error vs extraction failure.
  2. Retry once or twice with backoff; transient registry/network errors dominate.
  3. Verify the target exists on the registry's site.
  4. 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

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


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/c8fdcb94eb7d517c. Report an issue: GitHub.