charmbracelet/crush · error
failed to refresh OAuth token: %w
Error message
failed to refresh OAuth token: %w
What it means
This error wraps a transport-level failure that occurred while POSTing to /workspaces/{id}/config/refresh-oauth. The client could not complete the HTTP request (connection failure, timeout, request construction error), so RefreshOAuthToken aborts before reading any response. The underlying cause is preserved via %w.
Source
Thrown at internal/client/config.go:156
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)
}
return nil
}
// ProjectNeedsInitialization checks if the project needs
// initialization.
func (c *Client) ProjectNeedsInitialization(ctx context.Context, id string) (bool, error) {
rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/project/needs-init", id), nil, nil)
if err != nil {
return false, fmt.Errorf("failed to check project init: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return false, fmt.Errorf("failed to check project init: status code %d", rsp.StatusCode)View on GitHub (pinned to 7944b8e522)
Solutions
- Check that the server backing the client is running and reachable at the configured base URL
- Retry the refresh; OAuth refresh is idempotent server-side and transient network errors are the most common cause
- Inspect the wrapped error (errors.Unwrap / errors.As) to distinguish timeout, connection refused, or TLS problems
- Verify the workspace id is valid so the request is not rejected mid-flight
Example fix
// before
if err := client.RefreshOAuthToken(ctx, id, scope, providerID); err != nil {
return err
}
// after
if err := client.RefreshOAuthToken(ctx, id, scope, providerID); err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
return retryWithBackoff(ctx)
}
return fmt.Errorf("refresh oauth: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// Before calling, verify reachability
if u, err := url.Parse(client.BaseURL()); err != nil || u.Host == "" {
return fmt.Errorf("invalid client base URL")
}
conn, err := net.DialTimeout("tcp", u.Host, 3*time.Second)
if err != nil {
return fmt.Errorf("server unreachable: %w", err)
}
conn.Close() Type guard
func isTransportError(err error) bool {
var netErr net.Error
return errors.As(err, &netErr)
} Try / catch
if err := c.RefreshOAuthToken(ctx, id, scope, pid); err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// retry with backoff
}
return err
} Prevention
- Set generous but bounded context deadlines for OAuth refresh calls
- Retry transient network errors with exponential backoff before surfacing to the user
- Monitor server health and alert on refresh endpoint unavailability
- Pin and verify TLS/proxy configuration in CI environments
When it happens
Trigger: Calling Client.RefreshOAuthToken(ctx, id, scope, providerID) when the HTTP POST to /workspaces/{id}/config/refresh-oauth fails at the transport layer: server unreachable, connection reset, TLS error, or context deadline exceeded.
Common situations: Server is down or restarted while refreshing an expired provider OAuth token; DNS or proxy misconfiguration in CI; network flaps on laptops switching Wi-Fi; ctx deadline too short for a slow server.
Related errors
- failed to get MCP pending auth: %w
- failed to make request: %w
- failed to refresh OAuth token: status code %d
- failed to check project init: %w
- failed to mark project initialized: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/4ffba19c7904aa59.
Report an issue: GitHub.