{"record":{"id":"14aa04e9c2f8bd6d","repo":"microsoft/semantic-kernel","slug":"timeout-waiting-for-oauth-callback","errorCode":null,"errorMessage":"Timeout waiting for OAuth callback","messagePattern":"Timeout waiting for OAuth callback","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"python/samples/demos/mcp_with_oauth/agent/main.py","lineNumber":155,"sourceCode":"\n    def stop(self):\n        \"\"\"Stop the callback server.\"\"\"\n        if self.server:\n            self.server.shutdown()\n            self.server.server_close()\n        if self.thread:\n            self.thread.join(timeout=1)\n\n    def wait_for_callback(self, timeout=300):\n        \"\"\"Wait for OAuth callback with timeout.\"\"\"\n        start_time = time.time()\n        while time.time() - start_time < timeout:\n            if self.callback_data[\"authorization_code\"]:\n                return self.callback_data[\"authorization_code\"]\n            if self.callback_data[\"error\"]:\n                raise Exception(f\"OAuth error: {self.callback_data['error']}\")\n            time.sleep(0.1)\n        raise Exception(\"Timeout waiting for OAuth callback\")\n\n    def get_state(self):\n        \"\"\"Get the received state parameter.\"\"\"\n        return self.callback_data[\"state\"]\n\n\nasync def main():\n    # 1. Create the agent\n    callback_server = CallbackServer(port=3030)\n    callback_server.start()\n\n    async def callback_handler() -> tuple[str, str | None]:\n        \"\"\"Wait for OAuth callback and return auth code and state.\"\"\"\n        print(\"⏳ Waiting for authorization callback...\")\n        try:\n            auth_code = callback_server.wait_for_callback(timeout=300)\n            return auth_code, callback_server.get_state()\n        finally:","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/samples/demos/mcp_with_oauth/agent/main.py#L137-L173","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncode = callback_server.wait_for_callback()  # default 300s\n\n// after\ncode = callback_server.wait_for_callback(timeout=600)  # or fix redirect_uri registration","handlingStrategy":"retry","validationCode":"import socket\ndef port_open(host='127.0.0.1', port=3030) -> bool:\n    with socket.socket() as s:\n        return s.connect_ex((host, port)) == 0","typeGuard":null,"tryCatchPattern":"try:\n    code = callback_server.wait_for_callback(timeout=300)\nexcept Exception as e:\n    if 'Timeout' in str(e):\n        # verify redirect_uri registration / port, then retry once\n        raise\n    raise","preventionTips":["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."],"tags":["oauth","authentication","mcp","callback","timeout","network"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}