mastra-ai/mastra · error

OpenAI Codex OAuth is only available in Node.js environments

Error message

OpenAI Codex OAuth is only available in Node.js environments

What it means

The OpenAI Codex OAuth provider needs Node's crypto.randomBytes to generate the PKCE code verifier, but the lazily-resolved crypto import failed (e.g. dynamic import of 'node:crypto' rejected in a non-Node runtime). The library throws this to stop the browser-style OAuth flow in environments that cannot supply Node crypto. It is a hard environment gate, not a transient fault.

Source

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

    if (!response.ok) {
      const text = await response.text().catch(() => '');
      console.error('[openai-codex] Token refresh failed:', response.status, text);
      return { type: 'failed' };
    }

    return tokenResponseToResult((await response.json()) as TokenResponseJson, 'Token refresh');
  } catch (error) {
    console.error('[openai-codex] Token refresh error:', error);
    return { type: 'failed' };
  }
}

async function getRandomBytes() {
  if (!_randomBytes && _cryptoPromise) {
    _randomBytes = (await _cryptoPromise).randomBytes;
  }
  if (!_randomBytes) {
    throw new Error('OpenAI Codex OAuth is only available in Node.js environments');
  }
  return _randomBytes;
}

async function createAuthorizationFlow(
  redirectUri: string,
  state: string,
  originator: string = 'mastracode',
): Promise<{ verifier: string; url: string }> {
  const { verifier, challenge } = await generatePKCE();

  const url = new URL(AUTHORIZE_URL);
  url.searchParams.set('response_type', 'code');
  url.searchParams.set('client_id', CLIENT_ID);
  url.searchParams.set('redirect_uri', redirectUri);
  url.searchParams.set('scope', SCOPE);
  url.searchParams.set('code_challenge', challenge);
  url.searchParams.set('code_challenge_method', 'S256');

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Run the OAuth login flow in a Node.js runtime (>= 18), not in a browser or edge environment.
  2. If bundling, configure your bundler to keep node:crypto as an external/builtin (e.g. external: ['node:crypto'] in esbuild, resolve fallbacks off in webpack) instead of polyfilling it away.
  3. Switch tests/CI jobs that exercise OAuth to the node test environment (vitest environment: 'node') rather than jsdom.
  4. If the target platform truly cannot use Node crypto, use the device-authorization login path (loginOpenAICodexDevice) which uses fetch instead.

Example fix

// before: edge function that imports the provider
export const config = { runtime: 'edge' };
import { loginOpenAICodex } from 'mastracode/sdk';

// after: run login in a Node route
// next.config route on the Node.js runtime
export const config = { runtime: 'nodejs' };
import { loginOpenAICodex } from 'mastracode/sdk';
Defensive patterns

Strategy: validation

Validate before calling

import { createRequire } from 'module';
function canRunCodexOAuth(): boolean {
  try {
    const crypto = createRequire(import.meta.url)('node:crypto');
    return typeof crypto.randomBytes === 'function';
  } catch {
    return false;
  }
}
if (!canRunCodexOAuth()) useDeviceLoginInstead();

Try / catch

try {
  await loginOpenAICodex({});
} catch (e) {
  if (e.message.includes('only available in Node.js')) {
    await loginOpenAICodexDevice({}); // fetch-based fallback
  } else throw e;
}

Prevention

When it happens

Trigger: Calling loginOpenAICodex / createAuthorizationFlow (which calls getRandomBytes for PKCE generation) in a browser, edge worker (Cloudflare Workers, Vercel Edge), Deno/Bun without node:crypto compat, or a bundler that tree-shakes/stubs node:crypto so the dynamic import resolves without randomBytes.

Common situations: Running mastracode SDK code inside an edge runtime or serverless worker instead of a Node server; bundling with a browser target that aliases node:crypto; misconfigured test environment (jsdom/happy-dom) that lacks Node crypto globals; importing the provider into client-side code.

Related errors


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