can1357/oh-my-pi · error

The selected ChatGPT credential is not a valid JWT

Error message

The selected ChatGPT credential is not a valid JWT

What it means

jwtSubject() decodes the ChatGPT OAuth access token to extract the authenticated user id (sub or user_id claim). If the access token is not a decodable JWT, this error is thrown — the stored credential's access token is malformed or in an unexpected format.

Source

Thrown at packages/coding-agent/src/security/cloud.ts:161

	const currentStep = optionalString(raw.current_step);
	if (currentStep) configuration.currentStep = currentStep;
	const scanType = optionalString(scanInput.scan_type);
	if (scanType) configuration.scanType = scanType;
	const remainingScans = typeof raw.scans_remaining === "number" ? raw.scans_remaining : raw.remaining_scans;
	if (typeof remainingScans === "number" && Number.isFinite(remainingScans))
		configuration.remainingScans = remainingScans;
	if (typeof raw.total_scans === "number" && Number.isFinite(raw.total_scans))
		configuration.totalScans = raw.total_scans;
	const createdAt = optionalString(raw.created_at);
	if (createdAt) configuration.createdAt = createdAt;
	const updatedAt = optionalString(raw.updated_at);
	if (updatedAt) configuration.updatedAt = updatedAt;
	return configuration;
}

function jwtSubject(accessToken: string): string {
	const claims = decodeJwt(accessToken);
	if (!claims) throw new Error("The selected ChatGPT credential is not a valid JWT");
	return requiredString(claims.sub ?? claims.user_id, "authenticated user id");
}

export class CodexSecurityCloudHttpError extends Error {
	constructor(
		readonly status: number,
		readonly endpoint: string,
	) {
		super(`Codex Security cloud request failed (${status}) at ${endpoint}`);
		this.name = "CodexSecurityCloudHttpError";
	}
}

interface CloudRequestOptions {
	method?: "GET" | "POST";
	query?: Record<string, string | number | undefined>;
	body?: JsonObject | ((accessToken: string) => JsonObject);
	signal?: AbortSignal;

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-authenticate with the provider so a fresh, valid access token is stored
  2. Delete the malformed credential and log in again
  3. Inspect the stored access token (should be three dot-separated base64url segments) to confirm corruption

Example fix

// before
const subject = jwtSubject(account.accessToken); // throws
// after
await authStorage.refreshOrReauthenticate(provider); // obtain fresh JWT
const subject = jwtSubject(freshAccessToken);
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeJwt(token: string): boolean {
  const parts = token.split(".");
  return parts.length === 3 && parts.every(p => p.length > 0);
}
if (!looksLikeJwt(accessToken)) throw new Error("Stored access token is not a JWT");

Type guard

function isJwt(token: string): boolean {
  const parts = token.split(".");
  if (parts.length !== 3) return false;
  try { JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"))); return true; }
  catch { return false; }
}

Try / catch

try {
  const scan = await client.startScan(input);
} catch (err) {
  if (err.message.includes("not a valid JWT")) {
    await reauthenticate("openai-codex"); // replace corrupted token
  } else throw err;
}

Prevention

When it happens

Trigger: decodeJwt(accessToken) returns null: the pinned openai-codex credential's access token is not a JWT (corrupted storage, wrong token type stored, token truncated by an export/import).

Common situations: Manually edited or migrated auth storage; credential written by an older/newer client storing a non-JWT token; copy-paste truncation when seeding credentials.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f38902e58c326532. Report an issue: GitHub.