{"record":{"id":"9a17a4538e292ec7","repo":"gastownhall/beads","slug":"oauth-token-request-failed-w","errorCode":null,"errorMessage":"oauth: token request failed: %w","messagePattern":"oauth: token request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/linear/oauth.go","lineNumber":131,"sourceCode":"// acquireToken performs the client_credentials grant. Caller must hold m.mu write lock.\nfunc (m *OAuthTokenManager) acquireToken() error {\n\tdata := url.Values{\n\t\t\"grant_type\":    {\"client_credentials\"},\n\t\t\"client_id\":     {m.config.ClientID},\n\t\t\"client_secret\": {m.config.ClientSecret},\n\t\t\"scope\":         {m.config.Scopes},\n\t\t\"actor\":         {m.config.Actor},\n\t}\n\n\treq, err := http.NewRequest(\"POST\", m.config.TokenURL, strings.NewReader(data.Encode()))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"oauth: failed to create token request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\n\tresp, err := m.client.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"oauth: token request failed: %w\", err)\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) // 1MB limit\n\tif err != nil {\n\t\treturn fmt.Errorf(\"oauth: failed to read token response: %w\", err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tvar errResp oauthErrorResponse\n\t\tif json.Unmarshal(body, &errResp) == nil && errResp.Error != \"\" {\n\t\t\treturn fmt.Errorf(\"oauth: token request failed (%s): %s\", errResp.Error, errResp.Description)\n\t\t}\n\t\treturn fmt.Errorf(\"oauth: token request returned status %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar tokenResp oauthTokenResponse\n\tif err := json.Unmarshal(body, &tokenResp); err != nil {","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/oauth.go#L113-L149","documentation":"The OAuth token HTTP request itself failed at the transport level (connection refused, DNS failure, TLS error, timeout). The authorization server was unreachable, so no token could be issued.","triggerScenarios":"m.client.Do(req) returns an error inside acquireToken during a client-credentials token exchange.","commonSituations":"Corporate proxy or firewall blocking the token endpoint; DNS outage; TLS cert issues (self-signed MITM proxies); TokenURL pointing at a wrong host or a dead internal endpoint.","solutions":["Check network egress and proxy settings (HTTPS_PROXY) from the host running the code.","Verify TokenURL hostname resolves and is reachable (curl -v the endpoint).","Increase the HTTP client timeout if the failure is a timeout on a slow network.","Configure the http.Client's TLS settings if a corporate MITM certificate is in play."],"exampleFix":"// before\nclient: &http.Client{}\n// after\nclient: &http.Client{\n    Timeout: 15 * time.Second,\n    Transport: &http.Transport{Proxy: http.ProxyFromEnvironment},\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var netErr net.Error\nif errors.As(err, &netErr) && netErr.Timeout() {\n    // retry with exponential backoff\n}\n// otherwise surface the wrapped oauth error to the operator","preventionTips":["Set a sane HTTP client timeout and enable proxy-from-environment.","Monitor egress connectivity to the token endpoint in health checks.","Retry idempotent token fetches with jittered backoff."],"tags":["oauth","network","http-client","go"],"backgroundTag":"connection-refused","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}