Significant-Gravitas/AutoGPT · error · HTTPException

State token was not created for external OAuth flow

Error message

State token was not created for external OAuth flow

What it means

Raised (HTTP 400) by the external OAuth complete endpoint when the state token itself is valid but has no `callback_url` attached. Only state tokens created by the external authorize endpoint (which stores the external callback URL in the state metadata) are accepted here; states created by the platform's internal OAuth flow have `callback_url=None` and are rejected.

Source

Thrown at autogpt_platform/backend/backend/api/external/v1/integrations.py:426

    This endpoint should be called after the user has authorized the application
    and been redirected back to the external app's callback URL with an
    authorization code.
    """
    # Verify state token
    valid_state = await creds_manager.store.verify_state_token(
        auth.user_id, request.state_token, provider
    )

    if not valid_state:
        logger.warning(f"Invalid or expired state token for provider {provider}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Invalid or expired state token",
        )

    # Verify this is an external flow (callback_url must be set)
    if not valid_state.callback_url:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="State token was not created for external OAuth flow",
        )

    # Get OAuth handler with the original callback URL
    handler = _get_oauth_handler_for_external(provider, valid_state.callback_url)

    try:
        scopes = valid_state.scopes
        scopes = handler.handle_default_scopes(scopes)

        credentials = await handler.exchange_code_for_tokens(
            request.code, scopes, valid_state.code_verifier
        )

        # Handle Linear's space-separated scopes
        if len(credentials.scopes) == 1 and " " in credentials.scopes[0]:
            credentials.scopes = credentials.scopes[0].split(" ")

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Always create state via POST `/integrations/{provider}/oauth/authorize` with a `callback_url` before calling the external callback endpoint.
  2. Do not reuse state tokens obtained from the platform's internal login/OAuth flow.
  3. If stale states persist from an older version, restart the flow to generate a new external state.

Example fix

# before
state = start_internal_oauth(provider)          # no callback_url
POST /integrations/{provider}/oauth/callback {"state_token": state.token, ...}  # 400

# after
resp = POST /integrations/{provider}/oauth/authorize {"callback_url": "https://app.example.com/cb"}
POST /integrations/{provider}/oauth/callback {"state_token": resp.state_token, "code": "..."}
Defensive patterns

Strategy: validation

Validate before calling

# Only states created by the EXTERNAL authorize endpoint have a callback_url.
# Track provenance client-side:
state = authorize_external(provider, callback_url)  # marks state as external
assert state.origin == "external", "use /oauth/authorize with callback_url, not internal flow"

Try / catch

try:
    client.post(f"/integrations/{provider}/oauth/callback", json=cb)
except HTTPError as e:
    if e.response.status_code == 400 and "external OAuth flow" in e.response.text:
        raise FlowError("state came from internal flow; re-initiate via external authorize") from e
    raise

Prevention

When it happens

Trigger: POST `/api/external-api/v1/integrations/{provider}/oauth/callback` with a state token that came from the platform's own (internal) OAuth initiation instead of the external `/oauth/authorize` endpoint; or a state stored before the external-flow metadata field existed.

Common situations: Mixing the internal platform OAuth endpoints with the external API endpoints in one integration script; copying state examples from internal-flow docs; stale state rows persisted by an older backend version that lacked `callback_url` in `OAuthState`.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/e64eebcf40bde7fa. Report an issue: GitHub.