mastra-ai/mastra · error

OpenAI Codex device authorization response missing required…

Error message

OpenAI Codex device authorization response missing required fields

What it means

The device-authorization endpoint returned HTTP 200 but the JSON payload lacks the required fields: device_auth_id and a user code (user_code or usercode). The library validates the response shape before starting the polling loop, since polling would be meaningless without these identifiers. This is a defensive schema check against API contract changes or unexpected responses.

Solutions

  1. Update the mastracode SDK to the latest version so the response schema matches the current OpenAI API.
  2. Log/inspect the raw response body (temporarily) to confirm what the endpoint actually returned.
  3. Check for proxies/VPNs or captive portals that might replace the response with an HTML page.
  4. Retry later if OpenAI is mid-API-migration; report a bug with the raw payload if the SDK is current.

Example fix

// before: assuming fields exist
const { device_auth_id, user_code } = await response.json();

// after: validate defensively
const data = await response.json();
if (!data?.device_auth_id || !(data.user_code ?? data.usercode)) {
  throw new Error('Unexpected device-auth response: ' + JSON.stringify(data));
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidDeviceAuthResponse(d: unknown): d is { device_auth_id: string; user_code?: string; usercode?: string } {
  const o = d as any;
  return !!o && typeof o.device_auth_id === 'string' && (typeof o.user_code === 'string' || typeof o.usercode === 'string');
}

Type guard

function isDeviceAuthData(d: unknown): d is { device_auth_id: string; user_code?: string; usercode?: string; interval?: string | number } {
  const o = d as Record<string, unknown>;
  return typeof o?.device_auth_id === 'string' &&
    (typeof o?.user_code === 'string' || typeof o?.usercode === 'string');
}

Try / catch

try {
  const creds = await loginOpenAICodexDevice({});
} catch (e) {
  if (e.message.includes('missing required fields')) {
    console.error('OpenAI device-auth contract changed — update SDK, payload:', e);
  } else throw e;
}

Prevention

When it happens

Trigger: The device-auth endpoint responding with an unexpected JSON body — e.g. an error object with 200 status, a changed field name (OpenAI API contract change), a captive-portal/interstitial HTML parsed oddly, or an outdated CLIENT_ID receiving a different response schema.

Common situations: OpenAI changing/renaming device-auth response fields; an SDK version too old for the current API; proxy/VPN returning a login page with status 200; regional blocks returning a non-standard payload.

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/8e50fd6575de3dbf. Report an issue: GitHub.

Appendix: source

Thrown at mastracode/sdk/src/auth/providers/openai-codex.ts:438

    body: JSON.stringify({ client_id: CLIENT_ID, originator: 'mastracode' }),
    signal: options?.signal,
  });

  if (!response.ok) {
    throw new Error(`Failed to initiate OpenAI Codex device authorization: ${response.status}`);
  }

  const deviceData = (await response.json()) as {
    device_auth_id?: string;
    user_code?: string;
    usercode?: string;
    interval?: string | number;
  };

  const userCode = deviceData.user_code ?? deviceData.usercode;

  if (!deviceData.device_auth_id || !userCode) {
    throw new Error('OpenAI Codex device authorization response missing required fields');
  }

  const intervalSeconds =
    typeof deviceData.interval === 'number' ? deviceData.interval : Number.parseInt(deviceData.interval ?? '', 10) || 5;

  return {
    deviceAuthId: deviceData.device_auth_id,
    userCode,
    url: DEVICE_AUTHORIZE_URL,
    instructions: `Enter code: ${userCode}`,
    intervalMs: Math.max(intervalSeconds, 1) * 1000,
    deadlineAt: Date.now() + DEVICE_AUTH_TIMEOUT_MS,
  };
}

/**
 * Perform exactly one upstream poll for a pending Codex device login.
 * The Codex device endpoint signals "still pending" via HTTP 403/404 (it is

View on GitHub (pinned to 75dd419e61)