router-for-me/CLIProxyAPI · error · AuthenticationError
callback_timeout
callback_timeout
Error message
timeout waiting for OAuth callback
What it means
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.
Source
Thrown at internal/auth/claude/oauth_server.go:157
// WaitForCallback waits for the OAuth callback with a timeout.
// It blocks until either an OAuth result is received, an error occurs,
// or the specified timeout is reached.
//
// Parameters:
// - timeout: The maximum time to wait for the callback
//
// Returns:
// - *OAuthResult: The OAuth result if successful
// - error: An error if the callback times out or an error occurs
func (s *OAuthServer) WaitForCallback(timeout time.Duration) (*OAuthResult, error) {
select {
case result := <-s.resultChan:
return result, nil
case err := <-s.errorChan:
return nil, err
case <-time.After(timeout):
return nil, fmt.Errorf("timeout waiting for OAuth callback")
}
}
// handleCallback handles the OAuth callback endpoint.
// It extracts the authorization code and state from the callback URL,
// validates the parameters, and sends the result to the waiting channel.
//
// Parameters:
// - w: The HTTP response writer
// - r: The HTTP request
func (s *OAuthServer) handleCallback(w http.ResponseWriter, r *http.Request) {
log.Debug("Received OAuth callback")
// Validate request method
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}View on GitHub (pinned to 78f0c4079e)
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.
Example fix
# before (remote box, no forwarding — browser redirect never arrives) ssh user@server ./cli-proxy-api login # after ssh -L 53100:127.0.0.1:53100 user@server ./cli-proxy-api login --oauth-callback-port 53100
Defensive patterns
Strategy: retry
Validate before calling
if runtime.GOOS == "linux" && isRemoteSession() {
fmt.Println("Forward the callback port before continuing:", port)
} Try / catch
res, err := server.WaitForCallback(5 * time.Minute)
if err != nil && strings.Contains(err.Error(), "timeout waiting") {
res, err = restartFlowWithLongerTimeout(server, 10*time.Minute)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- timeout waiting for OAuth callback
- port_in_use
- Method not allowed
- OAuth error: %s
- No authorization code received
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/93d479b0f39435d4.
Report an issue: GitHub.