can1357/oh-my-pi · error · AIError.OAuthError
Device authorization response missing required fields
Error message
Device authorization response missing required fields
What it means
Thrown by loginOpenAICodexDevice when the device-authorization initiation returned HTTP 200 but the JSON payload lacks the required device_auth_id or user_code fields. Without these the CLI can neither display the code for the user nor poll for the token, so it fails fast with kind='validation'.
Source
Thrown at packages/ai/src/registry/oauth/openai-codex.ts:272
body: JSON.stringify({ client_id: CLIENT_ID }),
signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS),
});
if (!initResponse.ok) {
throw new AIError.OAuthError(`Device authorization initiation failed: ${initResponse.status}`, {
kind: "device-auth",
status: initResponse.status,
});
}
const initData = (await initResponse.json()) as {
device_auth_id?: string;
user_code?: string;
interval?: string | number;
};
if (!initData.device_auth_id || !initData.user_code) {
throw new AIError.OAuthError("Device authorization response missing required fields", { kind: "validation" });
}
const userCode = initData.user_code;
const pollIntervalMs =
(typeof initData.interval === "number"
? initData.interval
: parseInt(String(initData.interval ?? "5"), 10) || 5) *
1000 +
DEVICE_POLL_SAFETY_MARGIN_MS;
ctrl.onAuth?.({
url: DEVICE_AUTH_URL,
instructions: `Enter code: ${userCode}`,
});
ctrl.onProgress?.(`Waiting for browser authorization (code: ${userCode})…`);
for (let poll = 0; poll < DEVICE_MAX_POLLS; poll++) {View on GitHub (pinned to 9690622007)
Solutions
- Update the CLI so the expected field names match the current OpenAI device-auth API
- Inspect what the endpoint actually returns (curl with the same payload) to spot proxies or schema changes
- Disable/bypass intercepting proxies or VPNs and retry the login
- If OpenAI wrapped an error in a 200 body, wait and retry or check OpenAI status
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
// probe the device-auth endpoint shape before the full login
const res = await fetch(DEVICE_AUTH_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ client_id: CLIENT_ID }) });
const body = await res.json().catch(() => null);
if (!body || typeof body.device_auth_id !== 'string' || typeof body.user_code !== 'string') {
throw new Error('Unexpected device-auth response shape — update CLI or check proxy interference');
} Type guard
function isDeviceAuthInit(d: unknown): d is { device_auth_id: string; user_code: string; interval?: string | number } {
const v = d as Record<string, unknown> | null;
return !!v && typeof v.device_auth_id === 'string' && typeof v.user_code === 'string';
} Try / catch
try {
const auth = await loginOpenAICodexDevice();
} catch (e) {
if (e instanceof AIError.OAuthError && e.kind === 'validation' && e.message.includes('Device authorization response')) {
// update CLI / bypass proxy / retry
} else throw e;
} Prevention
- Update the CLI to track OpenAI device-auth schema changes
- Bypass intercepting proxies, VPNs, or captive portals that return 200 error pages
- Retry once on transient 200-wrapped errors under OpenAI load
- Validate responses with a type guard in wrappers around the login flow
When it happens
Trigger: OpenAI returns a 200 response whose body is an error object, a different schema (renamed fields after an API change), or an empty/HTML body misinterpreted as JSON — e.g. an intercepted response from a proxy or captive portal.
Common situations: Outdated CLI after OpenAI renamed device-auth response fields; network middleware (corporate proxy, antivirus) returning a 200 error page; OpenAI returning 200-wrapped errors under load.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Token response missing required fields
- Device authorization initiation failed: ${initResponse.statu
- Device authorization cancelled
- Credential ${id} is not OAuth (provider=${provider}, type=${
- Too many pending authorization requests. Please try again la
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8d5bbe7f692b4fd7.
Report an issue: GitHub.