unslothai/unsloth · warning · CodexAuthError

Paste the complete localhost ChatGPT callback URL.

Error message

Paste the complete localhost ChatGPT callback URL.

What it means

Raised as CodexAuthError by complete_browser_flow when the user-pasted callback URL does not structurally match the flow's registered redirect_uri: scheme, hostname, port, or path differ, or the URL contains a fragment. Because the expected URI is a localhost loopback with a dynamically assigned port, the port comparison is where most legitimate attempts fail.

Source

Thrown at studio/backend/core/inference/openai_codex_auth.py:619

        if flow.server:
            flow.server.close()
    return flow


async def complete_browser_flow(provider_id: str, flow_id: str, callback_url: str) -> OAuthFlow:
    flow = get_flow(provider_id, flow_id)
    if flow.method != "browser" or flow.status != "pending" or flow.consumed:
        raise CodexAuthError("Authorization flow is no longer active.")
    parsed = urlparse(callback_url)
    expected = urlparse(flow.redirect_uri)
    if (
        parsed.scheme != expected.scheme
        or parsed.hostname != expected.hostname
        or parsed.port != expected.port
        or parsed.path != expected.path
        or parsed.fragment
    ):
        raise CodexAuthError("Paste the complete localhost ChatGPT callback URL.")
    query = parse_qs(parsed.query)
    if not secrets.compare_digest(query.get("state", [""])[0], flow.state):
        raise CodexAuthError("Authorization state did not match.")
    code = query.get("code", [""])[0]
    if not code:
        raise CodexAuthError("The callback URL did not contain an authorization code.")
    await _exchange_code(flow, code)
    return flow


async def cancel_flow(flow_id: str) -> None:
    flow = _flows.pop(flow_id, None)
    if not flow:
        return
    flow.status = "cancelled"
    if flow.task:
        flow.task.cancel()
    if flow.cleanup_task and flow.cleanup_task is not asyncio.current_task():

View on GitHub (pinned to 203007d190)

Solutions

  1. Copy the FULL localhost URL from the browser address bar after the ChatGPT redirect, including http://, 127.0.0.1, the port, the path, and the entire query string.
  2. Do not use the auth.openai.com consent URL — only the 127.0.0.1 callback URL is valid here.
  3. If the port changed (flow restarted), paste the callback into the NEW flow's completion, not the old one.
  4. Trim whitespace and ensure no trailing fragment was added when pasting.

Example fix

// before
await codex_auth.complete_browser_flow(provider_id, flow_id, "https://auth.openai.com/authorize?...")

// after
# the URL the browser landed on AFTER consent, e.g.:
await codex_auth.complete_browser_flow(
    provider_id,
    flow_id,
    "http://127.0.0.1:53742/callback?state=...&code=...",
)
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

p = urlparse(callback_url)
e = urlparse(flow.redirect_uri)
if (p.scheme, p.hostname, p.port, p.path) != (e.scheme, e.hostname, e.port, e.path) or p.fragment:
    reject("pasted URL is not this flow's exact localhost callback")

Type guard

def callback_matches_redirect(callback_url: str, flow: codex_auth.OAuthFlow) -> bool:
    p, e = urlparse(callback_url), urlparse(flow.redirect_uri)
    return (
        p.scheme == e.scheme
        and p.hostname == e.hostname
        and p.port == e.port
        and p.path == e.path
        and not p.fragment
    )

Try / catch

try:
    flow = await codex_auth.complete_browser_flow(provider_id, flow_id, pasted)
except codex_auth.CodexAuthError as exc:
    if "complete localhost" in str(exc):
        ask_user_to_recopy_url()  # input problem; new flow not required
    else:
        raise

Prevention

When it happens

Trigger: The user pastes the authorization URL instead of the redirect URL; copies the URL without the port (browsers hide default ports); the paste is truncated before the path; a fragment (#...) is appended by the browser or an extension; the redirect landed on a different port than flow.redirect_uri recorded.

Common situations: Manual paste workflows where users grab the wrong URL from the address bar; mobile browsers stripping ports; URL shorteners or copy apps mangling the URL; users typing the URL by hand.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/d43b81b6015cb7e8. Report an issue: GitHub.