gastownhall/beads · error
oauth: failed to read token response: %w
Error message
oauth: failed to read token response: %w
What it means
The token endpoint responded, but reading the response body failed. The body is read with a 1MB limit via io.LimitReader, so this is an underlying read/IO error (connection reset mid-response, truncated chunked encoding), not an oversized body.
Source
Thrown at internal/linear/oauth.go:137
"scope": {m.config.Scopes},
"actor": {m.config.Actor},
}
req, err := http.NewRequest("POST", m.config.TokenURL, strings.NewReader(data.Encode()))
if err != nil {
return fmt.Errorf("oauth: failed to create token request: %w", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := m.client.Do(req)
if err != nil {
return fmt.Errorf("oauth: token request failed: %w", err)
}
defer func() { _ = resp.Body.Close() }()
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) // 1MB limit
if err != nil {
return fmt.Errorf("oauth: failed to read token response: %w", err)
}
if resp.StatusCode != http.StatusOK {
var errResp oauthErrorResponse
if json.Unmarshal(body, &errResp) == nil && errResp.Error != "" {
return fmt.Errorf("oauth: token request failed (%s): %s", errResp.Error, errResp.Description)
}
return fmt.Errorf("oauth: token request returned status %d: %s", resp.StatusCode, string(body))
}
var tokenResp oauthTokenResponse
if err := json.Unmarshal(body, &tokenResp); err != nil {
return fmt.Errorf("oauth: failed to parse token response: %w", err)
}
if tokenResp.AccessToken == "" {
return fmt.Errorf("oauth: token response missing access_token")
}View on GitHub (pinned to 71377f2769)
Solutions
- Retry the token request once with backoff; this failure is often transient.
- Check intermediaries (LB, proxy) for connection-reset logs around the time of failure.
- Ensure the token endpoint supports HTTP keep-alive correctly or test with HTTP/1.1 vs HTTP/2 toggles.
Defensive patterns
Strategy: retry
Try / catch
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.Canceled) {
// transient/truncated body — retry once with backoff
} Prevention
- Retry token acquisition; partial reads are usually transient.
- Avoid reusing flaky keep-alive connections for auth traffic.
- Check intermediary proxies for connection-reset issues.
When it happens
Trigger: io.ReadAll(io.LimitReader(resp.Body, 1<<20)) errors inside acquireToken after a successful HTTP response status line.
Common situations: Server or an intermediary closed the connection before the full body arrived; flaky mobile/VPN links; load balancer prematurely terminating chunked responses.
Related errors
- failed to read backup state: %w
- failed to write temp file: %w
- failed to sync temp file: %w
- failed to write issue %s: %w
- writing %s output: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d79e3110cea34f0f.
Report an issue: GitHub.