decolua/9router · error
Missing accessToken
Error message
Missing accessToken
What it means
After stripping server-controlled fields, each codex import item must carry a non-empty string accessToken (the ChatGPT/Codex OAuth access token). This check throws before the JWT backfill and connection creation, since a connection cannot be built without a token.
Source
Thrown at src/app/api/oauth/codex/bulk-import/route.js:73
for (let i = 0; i < accounts.length; i++) {
const raw = accounts[i];
try {
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
throw new Error("Item is not an object");
}
// Strip server-controlled fields
const {
id: _id,
provider: _provider,
authType: _authType,
createdAt: _createdAt,
updatedAt: _updatedAt,
...item
} = raw;
if (!item.accessToken || typeof item.accessToken !== "string") {
throw new Error("Missing accessToken");
}
// Backfill missing identity fields from JWT claims
const psd = item.providerSpecificData || {};
const needsEmail = !item.email;
const needsAccountId = !psd.chatgptAccountId;
const needsPlanType = !psd.chatgptPlanType;
if (needsEmail || needsAccountId || needsPlanType) {
const info = extractCodexAccountInfo(item.idToken || item.accessToken) || {};
if (needsEmail && info.email) item.email = info.email;
if (needsAccountId && info.chatgptAccountId) {
psd.chatgptAccountId = info.chatgptAccountId;
}
if (needsPlanType && info.chatgptPlanType) {
psd.chatgptPlanType = info.chatgptPlanType;
}
}View on GitHub (pinned to 90b52e06ff)
Solutions
- Add an accessToken string field to each item (snake_case access_token is not accepted here).
- If you only have access_token, rename the key to accessToken before importing.
- Re-export the accounts from the source tool ensuring tokens are included and not redacted.
Example fix
// before
{ "accounts": [{ "access_token": "eyJ..." }] }
// after
{ "accounts": [{ "accessToken": "eyJ..." }] } Defensive patterns
Strategy: validation
Validate before calling
for (const a of accounts) {
if (!a?.accessToken || typeof a.accessToken !== "string") {
throw new Error("each item needs a string accessToken");
}
} Type guard
const hasAccessToken = (x) => typeof x?.accessToken === "string" && x.accessToken.length > 0;
Try / catch
try {
await bulkImport(items);
} catch (e) {
if (e.message === "Missing accessToken") {
const fixed = items.map(({ access_token, ...r }) =>
({ accessToken: access_token ?? r.accessToken, ...r }));
} else throw e;
} Prevention
- Use the accessToken (camelCase) key — codex import does not read access_token
- Re-export accounts with tokens included, not redacted
- Run a schema check on the import file before POSTing
When it happens
Trigger: An accounts[] item in the codex bulk-import POST that lacks accessToken, has it under a different key (e.g. access_token), or has a non-string value (null, number, object).
Common situations: Import file exported from a tool using snake_case access_token instead of accessToken, redacted/stripped tokens from a shared config, or only refreshToken present.
Related errors
- Item is not an object
- Missing access_token / accessToken
- Kiro tool input must be a JSON object
- No Codex access token available. Please re-authorize the con
- A redeem request id is required to consume a Codex reset cre
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/f29b795752112d75.
Report an issue: GitHub.