{"record":{"id":"eaf000f00b9f1e4c","repo":"router-for-me/CLIProxyAPI","slug":"failed-to-create-token-request-w-eaf000","errorCode":null,"errorMessage":"failed to create token request: %w","messagePattern":"failed to create token request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/codex/openai_auth.go","lineNumber":118,"sourceCode":"\tif pkceCodes == nil {\n\t\treturn nil, fmt.Errorf(\"PKCE codes are required for token exchange\")\n\t}\n\tif strings.TrimSpace(redirectURI) == \"\" {\n\t\treturn nil, fmt.Errorf(\"redirect URI is required for token exchange\")\n\t}\n\n\t// Prepare token exchange request\n\tdata := url.Values{\n\t\t\"grant_type\":    {\"authorization_code\"},\n\t\t\"client_id\":     {ClientID},\n\t\t\"code\":          {code},\n\t\t\"redirect_uri\":  {strings.TrimSpace(redirectURI)},\n\t\t\"code_verifier\": {pkceCodes.CodeVerifier},\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", TokenURL, strings.NewReader(data.Encode()))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create token request: %w\", err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\treq.Header.Set(\"Accept\", \"application/json\")\n\n\tresp, err := o.httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"token exchange request failed: %w\", err)\n\t}\n\tdefer func() {\n\t\t_ = resp.Body.Close()\n\t}()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read token response: %w\", err)\n\t}\n\t// log.Debugf(\"Token response: %s\", string(body))","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/codex/openai_auth.go#L100-L136","documentation":"Returned when http.NewRequestWithContext fails while building the POST to the Codex token endpoint (TokenURL) during the OAuth authorization-code exchange. NewRequestWithContext only errors on an invalid method, a malformed URL, or a nil context — since method and URL are hardcoded constants here, in practice this indicates a nil or canceled context rather than anything about the network.","triggerScenarios":"Calling ExchangeCode with a context that is already canceled or expired; passing context.Background() that was canceled upstream by a signal handler; theoretically a corrupted TokenURL constant after local modifications.","commonSituations":"Ctrl+C or a shutdown signal cancels the parent context mid-login; a wrapper cancels the auth timeout context before the exchange step begins; almost never seen in normal operation because the URL and method are fixed.","solutions":["Check the ctx passed into the exchange for prior cancellation (errors.Is(err, context.Canceled)).","Pass a fresh, non-canceled context (context.Background() or one with an adequate timeout) for the login flow.","If it persists, verify TokenURL in internal/auth/codex has not been modified locally."],"exampleFix":"// before\nctx, cancel := context.WithCancel(context.Background())\ncancel() // canceled too early\ntok, err := auth.ExchangeCode(ctx, code)\n\n// after\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\ntok, err := auth.ExchangeCode(ctx, code)","handlingStrategy":"validation","validationCode":"if ctx == nil || ctx.Err() != nil {\n    return fmt.Errorf(\"exchange aborted before start: %w\", ctx.Err())\n}\ntok, err := auth.ExchangeCode(ctx, code)","typeGuard":null,"tryCatchPattern":"tok, err := auth.ExchangeCode(ctx, code)\nif err != nil {\n    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {\n        // context problem, not provider problem: rebuild ctx and restart flow\n    }\n    return err\n}","preventionTips":["Pass a fresh context.WithTimeout sized for the whole interactive login.","Never reuse request-scoped contexts for multi-step OAuth flows.","Handle SIGINT so shutdown does not cancel a login mid-exchange silently."],"tags":["oauth","codex","context","http-request","auth-flow"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}