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
- 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.
- Do not use the auth.openai.com consent URL — only the 127.0.0.1 callback URL is valid here.
- If the port changed (flow restarted), paste the callback into the NEW flow's completion, not the old one.
- 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
- Instruct users to copy the full post-redirect localhost URL including port and query.
- Validate the URL shape client-side before submitting (same comparisons as the guard).
- Warn when the pasted host is auth.openai.com — that is the consent page, not the callback.
- Trim whitespace and strip fragments on paste.
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
- The callback URL did not contain an authorization code.
- ChatGPT credential update is busy. Please retry.
- ChatGPT returned an invalid access token.
- The ChatGPT account identifier was missing.
- ChatGPT returned an invalid token response.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/d43b81b6015cb7e8.
Report an issue: GitHub.