xtekky/gpt4free · error · RuntimeError
OAuth callback timed out
Error message
OAuth callback timed out
What it means
The local OAuth callback server's wait_for_callback() returned a falsy result: no callback request arrived before the wait expired, so the browser never hit the localhost redirect. The login flow cannot obtain an authorization code without that redirect.
Source
Thrown at g4f/Provider/needs_auth/GeminiCLI.py:1217
print("Please open the URL above manually.\n")
else:
if not server_started:
print(
f"\nCould not start local callback server on port {GEMINICLI_OAUTH_CALLBACK_PORT}."
)
print("You may need to close any application using that port.\n")
print(f"\nPlease open this URL in your browser:\n")
print(f"{auth_url}\n")
if server_started:
print("Waiting for authentication callback...")
try:
callback_result = callback_server.wait_for_callback()
if not callback_result:
raise RuntimeError("OAuth callback timed out")
code = callback_result.get("code")
callback_state = callback_result.get("state")
if not code:
raise RuntimeError("No authorization code received")
print("\n✓ Authorization code received. Exchanging for tokens...")
tokens = await cls.exchange_code_for_tokens(
code, callback_state or state
)
print(f"✓ Authentication successful!")
if tokens.get("email"):
print(f" Logged in as: {tokens['email']}")
return tokensView on GitHub (pinned to 973504e177)
Solutions
- Ensure the machine running g4f is the same machine the browser runs on, or forward the callback port
- Free the callback port (the flow prints which one) and retry
- If port binding is impossible, use the manual paste mode instead of the callback server
- Complete the Google consent screen promptly after opening the URL
Defensive patterns
Strategy: retry
Validate before calling
import socket
def callback_port_free(port: int) -> bool:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.bind(("127.0.0.1", port))
return True
except OSError:
return False Try / catch
for attempt in range(2):
try:
tokens = await GeminiCLI.login()
break
except RuntimeError as e:
if "OAuth callback timed out" in str(e) and attempt == 0:
continue # user was slow; try again with a fresh URL
raise Prevention
- Run login on the same host as the browser, or port-forward the callback
- Free the callback port before starting; the flow prints it on conflict
- Open the auth URL immediately and complete consent without long pauses
When it happens
Trigger: User opens the auth URL but does not complete consent, or consent redirects elsewhere; the localhost callback server is blocked (port in use, firewall, remote container) so the redirect never reaches it.
Common situations: Running login inside a container or remote host where localhost is not the browser's localhost; another process holding the callback port; user closes the tab; slow consent flow exceeding the wait window.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- OAuth callback timed out
- Missing PKCE verifier in state parameter
- Token exchange failed: {error_text}
- Missing tokens in response
- No authorization code received
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/3209acaddb532956.
Report an issue: GitHub.