{"record":{"id":"93d479b0f39435d4","repo":"router-for-me/CLIProxyAPI","slug":"callback-timeout","errorCode":"callback_timeout","errorMessage":"timeout waiting for OAuth callback","messagePattern":"timeout waiting for OAuth callback","errorType":"console","errorClass":"AuthenticationError","httpStatus":408,"severity":"error","filePath":"internal/auth/claude/oauth_server.go","lineNumber":157,"sourceCode":"\n// WaitForCallback waits for the OAuth callback with a timeout.\n// It blocks until either an OAuth result is received, an error occurs,\n// or the specified timeout is reached.\n//\n// Parameters:\n//   - timeout: The maximum time to wait for the callback\n//\n// Returns:\n//   - *OAuthResult: The OAuth result if successful\n//   - error: An error if the callback times out or an error occurs\nfunc (s *OAuthServer) WaitForCallback(timeout time.Duration) (*OAuthResult, error) {\n\tselect {\n\tcase result := <-s.resultChan:\n\t\treturn result, nil\n\tcase err := <-s.errorChan:\n\t\treturn nil, err\n\tcase <-time.After(timeout):\n\t\treturn nil, fmt.Errorf(\"timeout waiting for OAuth callback\")\n\t}\n}\n\n// handleCallback handles the OAuth callback endpoint.\n// It extracts the authorization code and state from the callback URL,\n// validates the parameters, and sends the result to the waiting channel.\n//\n// Parameters:\n//   - w: The HTTP response writer\n//   - r: The HTTP request\nfunc (s *OAuthServer) handleCallback(w http.ResponseWriter, r *http.Request) {\n\tlog.Debug(\"Received OAuth callback\")\n\n\t// Validate request method\n\tif r.Method != http.MethodGet {\n\t\thttp.Error(w, \"Method not allowed\", http.StatusMethodNotAllowed)\n\t\treturn\n\t}","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/claude/oauth_server.go#L139-L175","documentation":"WaitForCallback waited the full timeout without receiving the browser redirect on resultChan and without a server error. It carries code=callback_timeout: the login server was up, but the authorization code never arrived in time. Almost always the human/browser side of the flow, not the network stack.","triggerScenarios":"User opened the consent page but never clicked approve; browser redirected to a different host/port than the callback server's (wrong --oauth-callback-port or redirect URI); user is on a remote/HEADLESS machine and the opened browser is not reachable from the server's host; the default timeout elapsed before the user completed login.","commonSituations":"Headless servers where the auth URL is printed but the callback would hit the wrong machine; SSH sessions without port forwarding; corporate browsers blocking localhost redirects; slow SSO/MFA flows exceeding the default wait; mistyped callback port so the browser hits a dead port.","solutions":["Re-run login and complete the browser step promptly; if on a remote host, forward the callback port (ssh -L <port>:127.0.0.1:<port>) so the redirect reaches the server.","Verify the redirect URI/port in the auth URL matches the server's actual port (check --oauth-callback-port).","Increase the callback wait timeout if your SSO/MFA flow is slow.","Ensure nothing (firewall, browser policy) blocks the browser from reaching http://127.0.0.1:<port>/callback."],"exampleFix":"# before (remote box, no forwarding — browser redirect never arrives)\nssh user@server\n./cli-proxy-api login\n\n# after\nssh -L 53100:127.0.0.1:53100 user@server\n./cli-proxy-api login --oauth-callback-port 53100","handlingStrategy":"retry","validationCode":"if runtime.GOOS == \"linux\" && isRemoteSession() {\n    fmt.Println(\"Forward the callback port before continuing:\", port)\n}","typeGuard":null,"tryCatchPattern":"res, err := server.WaitForCallback(5 * time.Minute)\nif err != nil && strings.Contains(err.Error(), \"timeout waiting\") {\n    res, err = restartFlowWithLongerTimeout(server, 10*time.Minute)\n}","preventionTips":["For remote hosts, SSH-forward the callback port and print the auth URL rather than auto-opening a browser.","Budget the timeout for your SSO/MFA reality; 1-2 min fails on slow corporate flows."],"tags":["claude","oauth","timeout","auth-flow","callback"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}