{"record":{"id":"f67d002224a17836","repo":"microsoft/semantic-kernel","slug":"oauth-error-self-callback-data-error","errorCode":null,"errorMessage":"OAuth error: {self.callback_data['error']}","messagePattern":"OAuth error: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"python/samples/demos/mcp_with_oauth/agent/main.py","lineNumber":153,"sourceCode":"        self.thread.start()\n        print(f\"🖥️  Started callback server on http://localhost:{self.port}\")\n\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)","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/samples/demos/mcp_with_oauth/agent/main.py#L135-L171","documentation":"Raised by CallbackServer.wait_for_callback when callback_data['error'] is set — the OAuth provider redirected back with an error parameter (e.g. access_denied, invalid_request). The sample polls callback_data in a loop and surfaces any error reported by the authorization server.","triggerScenarios":"The user denies consent; the OAuth provider returns an error code in the redirect; the redirect URL carries an 'error' query/form field for any reason (bad client_id, mismatched redirect_uri, expired state).","commonSituations":"End-user clicks 'Deny' on the consent screen; misconfigured client_id/redirect_uri at the provider; clock skew or expired authorization; provider maintenance returning errors.","solutions":["Inspect callback_data['error'] (and any error_description) to identify the specific OAuth error code.","For access_denied, re-prompt the user or fall back to a non-OAuth path.","For configuration errors, verify client_id, redirect_uri, and scopes against the provider's app registration.","Re-initiate the OAuth flow with a fresh state token."],"exampleFix":"// before\n# no error handling around wait_for_callback\ncode = callback_server.wait_for_callback()\n\n// after\ntry:\n    code = callback_server.wait_for_callback()\nexcept Exception as e:\n    print(f'OAuth failed: {e}')\n    # re-initiate flow or exit gracefully","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    code = callback_server.wait_for_callback()\nexcept Exception as e:\n    error = callback_server.callback_data.get('error')\n    if error == 'access_denied':\n        # re-prompt or fallback\n        pass\n    else:\n        raise","preventionTips":["Surface OAuth error codes (and error_description) to the user clearly.","Verify client_id/redirect_uri/scopes at the provider before starting the flow.","Re-initiate with a fresh state on transient provider errors."],"tags":["oauth","authentication","mcp","callback","network"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}