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
- Run the OAuth login flow in a Node.js runtime (>= 18), not in a browser or edge environment.
- 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.
- Switch tests/CI jobs that exercise OAuth to the node test environment (vitest environment: 'node') rather than jsdom.
- 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
- Only import/invoke the OAuth provider from Node.js entry points.
- Keep node: builtins external in bundler configs.
- Use vitest environment 'node' for auth tests.
- Prefer the device-login flow in edge/serverless targets.
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
- Snapshot functionality requires a Node.js environment. impor
- Invalid state token format
- Invalid or tampered state token
- Invalid state token payload
- Redirect URI is required for SSO. Set AUTH0_REDIRECT_URI or
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/738534458d24b8f9.
Report an issue: GitHub.