microsoft/semantic-kernel · error · Exception

OAuth error: {self.callback_data['error']}

Error message

OAuth error: {self.callback_data['error']}

What it means

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.

Source

Thrown at python/samples/demos/mcp_with_oauth/agent/main.py:153

        self.thread.start()
        print(f"🖥️  Started callback server on http://localhost:{self.port}")

    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)

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Inspect callback_data['error'] (and any error_description) to identify the specific OAuth error code.
  2. For access_denied, re-prompt the user or fall back to a non-OAuth path.
  3. For configuration errors, verify client_id, redirect_uri, and scopes against the provider's app registration.
  4. Re-initiate the OAuth flow with a fresh state token.

Example fix

// before
# no error handling around wait_for_callback
code = callback_server.wait_for_callback()

// after
try:
    code = callback_server.wait_for_callback()
except Exception as e:
    print(f'OAuth failed: {e}')
    # re-initiate flow or exit gracefully
Defensive patterns

Strategy: try-catch

Try / catch

try:
    code = callback_server.wait_for_callback()
except Exception as e:
    error = callback_server.callback_data.get('error')
    if error == 'access_denied':
        # re-prompt or fallback
        pass
    else:
        raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/f67d002224a17836. Report an issue: GitHub.