charmbracelet/crush · error

failed to decode session agent queued prompts: %w

Error message

failed to decode session agent queued prompts: %w

What it means

After a 200 response, GetAgentSessionQueuedPrompts decodes the body as a bare JSON integer. If the body is not a valid JSON number (HTML error page, empty body, object wrapper, truncated response), json.Decode fails and this error wraps the decode failure.

Source

Thrown at internal/client/proto.go:438

		return fmt.Errorf("failed to refresh MCP resources: status code %d", rsp.StatusCode)
	}
	return nil
}

// GetAgentSessionQueuedPrompts retrieves the number of queued prompts for a
// session.
func (c *Client) GetAgentSessionQueuedPrompts(ctx context.Context, id string, sessionID string) (int, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/agent/sessions/%s/prompts/queued", id, sessionID), nil, nil)
	if err != nil {
		return 0, fmt.Errorf("failed to get session agent queued prompts: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return 0, fmt.Errorf("failed to get session agent queued prompts: status code %d", rsp.StatusCode)
	}
	var count int
	if err := json.NewDecoder(rsp.Body).Decode(&count); err != nil {
		return 0, fmt.Errorf("failed to decode session agent queued prompts: %w", err)
	}
	return count, nil
}

// ClearAgentSessionQueuedPrompts clears the queued prompts for a session.
func (c *Client) ClearAgentSessionQueuedPrompts(ctx context.Context, id string, sessionID string) error {
	rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/sessions/%s/prompts/clear", id, sessionID), nil, nil, nil)
	if err != nil {
		return fmt.Errorf("failed to clear session agent queued prompts: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return fmt.Errorf("failed to clear session agent queued prompts: status code %d", rsp.StatusCode)
	}
	return nil
}

// GetAgentInfo retrieves the agent status for a workspace.

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify client and server versions match (plain int response expected)
  2. Dump the raw response body to see what was actually returned
  3. Check for proxies/middleware rewriting the response
  4. Update the client to match the server's current response schema

Example fix

// before
var count int
if err := json.NewDecoder(rsp.Body).Decode(&count); err != nil {
	return 0, fmt.Errorf("failed to decode session agent queued prompts: %w", err)
}
// after
body, _ := io.ReadAll(rsp.Body)
var count int
if err := json.Unmarshal(body, &count); err != nil {
	return 0, fmt.Errorf("decode queued prompts %q: %w", body, err)
}
Defensive patterns

Strategy: type-guard

Type guard

func decodeQueuedCount(body io.Reader) (int, error) {
	dec := json.NewDecoder(body)
	var n int
	if err := dec.Decode(&n); err != nil {
		return 0, fmt.Errorf("expected JSON int, got: %w", err)
	}
	return n, nil
}

Try / catch

n, err := client.GetAgentSessionQueuedPrompts(ctx, wsID, sid)
if err != nil && strings.Contains(err.Error(), "failed to decode session agent queued prompts") {
	// log raw body / check version mismatch instead of retrying blindly
}

Prevention

When it happens

Trigger: Server returns 200 with an unexpected body: a proxy injecting HTML, an empty body, or an API version returning {"count": N} instead of a plain int.

Common situations: API version mismatch between client and server; misconfigured reverse proxy returning a login page with 200; server bug changing the response shape.

Understand the failure class

Related errors


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