charmbracelet/crush · error
failed to decode import copilot response: %w
Error message
failed to decode import copilot response: %w
What it means
After a 200 response, ImportCopilot decodes the JSON body containing the imported token and success flag. If the body is not valid JSON or does not match the expected shape, this error wraps the decode failure.
Source
Thrown at internal/client/config.go:143
}
// ImportCopilot attempts to import a GitHub Copilot token on the
// server.
func (c *Client) ImportCopilot(ctx context.Context, id string) (*oauth.Token, bool, error) {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/config/import-copilot", id), nil, nil, nil)
if err != nil {
return nil, false, fmt.Errorf("failed to import copilot: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, false, fmt.Errorf("failed to import copilot: status code %d", rsp.StatusCode)
}
var result struct {
Token *oauth.Token `json:"token"`
Success bool `json:"success"`
}
if err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {
return nil, false, fmt.Errorf("failed to decode import copilot response: %w", err)
}
return result.Token, result.Success, nil
}
// RefreshOAuthToken refreshes an OAuth token for a provider on the
// server.
func (c *Client) RefreshOAuthToken(ctx context.Context, id string, scope config.Scope, providerID string) error {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/config/refresh-oauth", id), nil, jsonBody(struct {
Scope config.Scope `json:"scope"`
ProviderID string `json:"provider_id"`
}{Scope: scope, ProviderID: providerID}), http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return fmt.Errorf("failed to refresh OAuth token: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to refresh OAuth token: status code %d", rsp.StatusCode)
}View on GitHub (pinned to 7944b8e522)
Solutions
- Inspect the wrapped %w error and capture the raw response body for diagnosis
- Check whether a proxy or middleware is rewriting the response
- Ensure client and server versions are compatible
- Retry; if persistent, report a server bug returning invalid JSON with 200
Defensive patterns
Strategy: type-guard
Validate before calling
// sanity-check the endpoint returns JSON before decoding dump, _ := c.ImportCopilot(ctx, wsID) // if this errors with decode, log raw body via server logs
Type guard
func isJSONContentType(h http.Header) bool {
return strings.Contains(h.Get("Content-Type"), "application/json")
} Try / catch
tok, ok, err := c.ImportCopilot(ctx, wsID)
if err != nil {
if strings.Contains(err.Error(), "failed to decode") {
// likely a proxy or server bug returning non-JSON with 200
return diagnoseRawResponse(ctx, wsID)
}
return err
} Prevention
- Bypass or check proxies/captive portals that rewrite responses
- Keep client and server schemas in sync (same release train)
- Log the raw body on decode failures for debugging
When it happens
Trigger: Server returns 200 with malformed, empty, or non-JSON body for import-copilot (e.g. a proxy intercepting the response, or server bug returning an error page with 200).
Common situations: Reverse proxy or captive portal returning HTML with status 200; server/client version mismatch changing the response schema; truncated response.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to decode response: %w
- failed to unmarshal response: %w
- failed to decode MCP prompt response: %w
- failed to decode LSP diagnostics: %w
- failed to decode LSPs: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/979c88448890cdee.
Report an issue: GitHub.