microsoft/semantic-kernel · error · Exception
Timeout waiting for OAuth callback
Error message
Timeout waiting for OAuth callback
What it means
Raised by CallbackServer.wait_for_callback when the 300-second (default) timeout elapses without receiving an authorization_code and without an error. The local callback server polls callback_data every 0.1s; if no callback ever arrives, it gives up.
Source
Thrown at python/samples/demos/mcp_with_oauth/agent/main.py:155
def stop(self):
"""Stop the callback server."""
if self.server:
self.server.shutdown()
self.server.server_close()
if self.thread:
self.thread.join(timeout=1)
def wait_for_callback(self, timeout=300):
"""Wait for OAuth callback with timeout."""
start_time = time.time()
while time.time() - start_time < timeout:
if self.callback_data["authorization_code"]:
return self.callback_data["authorization_code"]
if self.callback_data["error"]:
raise Exception(f"OAuth error: {self.callback_data['error']}")
time.sleep(0.1)
raise Exception("Timeout waiting for OAuth callback")
def get_state(self):
"""Get the received state parameter."""
return self.callback_data["state"]
async def main():
# 1. Create the agent
callback_server = CallbackServer(port=3030)
callback_server.start()
async def callback_handler() -> tuple[str, str | None]:
"""Wait for OAuth callback and return auth code and state."""
print("⏳ Waiting for authorization callback...")
try:
auth_code = callback_server.wait_for_callback(timeout=300)
return auth_code, callback_server.get_state()
finally:View on GitHub (pinned to c028a0c7dc)
Solutions
- Verify the OAuth redirect_uri in the provider app registration points to the callback server's host:port (e.g. http://localhost:3030/callback).
- Confirm port 3030 is free and reachable locally; change the port and redirect_uri together if needed.
- Increase the timeout argument if the user legitimately needs more time.
- Ensure the user actually completes the consent flow in the browser.
Example fix
// before code = callback_server.wait_for_callback() # default 300s // after code = callback_server.wait_for_callback(timeout=600) # or fix redirect_uri registration
Defensive patterns
Strategy: retry
Validate before calling
import socket
def port_open(host='127.0.0.1', port=3030) -> bool:
with socket.socket() as s:
return s.connect_ex((host, port)) == 0 Try / catch
try:
code = callback_server.wait_for_callback(timeout=300)
except Exception as e:
if 'Timeout' in str(e):
# verify redirect_uri registration / port, then retry once
raise
raise Prevention
- Register redirect_uri to the callback server's exact host:port.
- Ensure the callback port is free and not firewalled.
- Confirm the user completes consent before the timeout.
When it happens
Trigger: The OAuth redirect never reaches the local callback server (port 3030); the user closed the browser before completing consent; the redirect_uri is misrouted; a firewall blocks the inbound callback; the callback server failed to bind.
Common situations: Wrong redirect_uri registered so the provider redirects elsewhere; the local port (3030) is already in use or firewalled; the user abandons the flow; network/VPN blocking localhost callbacks.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- OAuth error: {self.callback_data['error']}
- Missing state parameter
- Missing state parameter
- Missing state parameter
- Missing username, password, or state parameter
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/14aa04e9c2f8bd6d.
Report an issue: GitHub.