charmbracelet/crush · error

failed to list skills: %w

Error message

failed to list skills: %w

What it means

This error is returned by Client.ListSkills when the underlying HTTP GET request to /workspaces/{id}/skills fails at the transport level. The library wraps the original error (connection failure, timeout, context cancellation, invalid URL) with %w so the root cause remains inspectable via errors.Is/As. It indicates the request never completed successfully enough to receive an HTTP response.

Source

Thrown at internal/client/config.go:223

	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("failed to get init prompt: status code %d", rsp.StatusCode)
	}
	var result struct {
		Prompt string `json:"prompt"`
	}
	if err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {
		return "", fmt.Errorf("failed to decode init prompt response: %w", err)
	}
	return result.Prompt, nil
}

// ListSkills retrieves the visible skills for a workspace.
func (c *Client) ListSkills(ctx context.Context, id string) ([]proto.SkillInfo, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/skills", id), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to list skills: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to list skills: status code %d", rsp.StatusCode)
	}
	var skills []proto.SkillInfo
	if err := json.NewDecoder(rsp.Body).Decode(&skills); err != nil {
		return nil, fmt.Errorf("failed to decode skills: %w", err)
	}
	return skills, nil
}

// ReadSkill reads a skill's content by ID from the server.
func (c *Client) ReadSkill(ctx context.Context, id, skillID string) (*proto.ReadSkillResponse, error) {
	rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/skills/read", id), nil, jsonBody(proto.ReadSkillRequest{
		SkillID: skillID,
	}), http.Header{"Content-Type": []string{"application/json"}})
	if err != nil {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify the client's base URL/host points at a running server (curl the /health or any endpoint).
  2. Check network connectivity to the server (DNS, firewall, proxy, VPN).
  3. Inspect the wrapped cause with errors.Unwrap or %v to see the transport error (e.g. connection refused vs timeout).
  4. Increase or fix the context deadline passed to ListSkills if timeouts are the cause.
  5. Retry with backoff if the failure is transient (server restarting).

Example fix

// before
skills, err := client.ListSkills(ctx, wsID)
if err != nil { return err }
// after
skills, err := client.ListSkills(ctx, wsID)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        return fmt.Errorf("skills listing timed out, check server health: %w", err)
    }
    return fmt.Errorf("is the server running? %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: pre-check server reachability
func serverReachable(baseURL string) error {
    resp, err := http.Get(baseURL + "/health")
    if err != nil { return err }
    defer resp.Body.Close()
    return nil
}

Type guard

func isTransportError(err error) bool {
    var ne net.Error
    return errors.As(err, &ne) || errors.Is(err, context.DeadlineExceeded) || errors.Is(err, syscall.ECONNREFUSED)
}

Try / catch

skills, err := client.ListSkills(ctx, wsID)
if err != nil {
    if isTransportError(err) {
        // retry or surface 'server unreachable'
        return retryOrFallback(err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Client.ListSkills(ctx, workspaceID) when the server is unreachable, the connection is refused/reset, the context deadline expires mid-request, or c.get fails to construct/execute the request.

Common situations: Server process not running or wrong base URL/port configured; network partition, VPN or proxy blocking the request; context cancelled because a parent operation timed out; TLS certificate issues in self-hosted setups.

Related errors


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