gastownhall/beads · error
failed to get OAuth token: %w
Error message
failed to get OAuth token: %w
What it means
When the Linear client is in OAuth auth mode, authHeader obtains an access token from the client's TokenManager to build the Authorization header. If the token manager cannot produce a token (refresh failure, expired refresh token, network problem reaching the token endpoint), the error is wrapped as 'failed to get OAuth token'. It propagates to executeOnce and createIssueSingleAttempt, which surface it to the caller.
Source
Thrown at internal/linear/client.go:214
APIKey: c.APIKey,
TeamID: c.TeamID,
ProjectID: projectID,
Endpoint: c.Endpoint,
HTTPClient: c.HTTPClient,
AuthMode: c.AuthMode,
TokenManager: c.TokenManager,
RateLimitFloor: c.RateLimitFloor,
rateLimitState: c.rateLimitState,
}
}
// authHeader returns the Authorization header value for this client.
func (c *Client) authHeader() (string, error) {
switch c.AuthMode {
case AuthModeOAuth:
token, err := c.TokenManager.Token()
if err != nil {
return "", fmt.Errorf("failed to get OAuth token: %w", err)
}
return "Bearer " + token, nil
default:
return c.APIKey, nil
}
}
// WithRateLimitFloor returns a new client with the specified rate-limit circuit-breaker floor.
// When remaining API quota drops below this value, Execute returns ErrRateLimitExhausted.
func (c *Client) WithRateLimitFloor(floor int) *Client {
return &Client{
APIKey: c.APIKey,
TeamID: c.TeamID,
ProjectID: c.ProjectID,
Endpoint: c.Endpoint,
HTTPClient: c.HTTPClient,
AuthMode: c.AuthMode,
TokenManager: c.TokenManager,View on GitHub (pinned to 71377f2769)
Solutions
- Re-authenticate the OAuth integration to obtain a fresh refresh token
- Check the wrapped (%w) inner error — refresh failure vs network — and fix accordingly
- Verify the token endpoint is reachable (proxy/firewall/DNS)
- Alternatively configure API-key auth mode if OAuth is not required
- Ensure the system clock is correct
Defensive patterns
Strategy: try-catch
Validate before calling
if client.AuthMode == linear.AuthModeOAuth {
if _, err := client.TokenManager.Token(); err != nil {
return fmt.Errorf("OAuth not usable: %w", err)
}
} Try / catch
data, err := client.Execute(ctx, req)
if err != nil {
var tokErr *fmt.WrapError // or errors.As on the underlying token error
if errors.Is(err, oauth.ErrTokenExpired) || strings.Contains(err.Error(), "failed to get OAuth token") {
if rerr := refreshCredentials(ctx); rerr != nil { return rerr }
data, err = client.Execute(ctx, req)
}
if err != nil { return err }
} Prevention
- Refresh tokens proactively before expiry rather than lazily
- Re-authenticate when refresh tokens expire instead of retrying indefinitely
- Monitor token-endpoint reachability in health checks
- Use API-key mode for long-lived unattended processes where OAuth refresh is impractical
When it happens
Trigger: Any API call (Execute / createIssueSingleAttempt) with c.AuthMode == AuthModeOAuth where TokenManager.Token() fails — e.g. expired access token with failed refresh, revoked refresh token, or unreachable OAuth token endpoint.
Common situations: Long-running processes whose refresh token expired; revoked OAuth app credentials; corporate proxy blocking the token endpoint; clock skew causing premature token expiry; switching between API-key and OAuth config without updating AuthMode.
Related errors
- --auth-token-file: %w
- no Linear client available
- missing external ref for Linear issue %s
- Linear project milestone is missing id
- updating Linear milestone epic %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ee148211cab34b69.
Report an issue: GitHub.