{"record":{"id":"1b9e5e389e0ba390","repo":"jlcodes99/cockpit-tools","slug":"sub2api-api-key-missing","errorCode":"SUB2API_API_KEY_MISSING","errorMessage":"SUB2API_API_KEY_MISSING","messagePattern":"SUB2API_API_KEY_MISSING","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils/codexExportFormats.ts","lineNumber":355,"sourceCode":"  }\n\n  const planType = resolvePlanType(account);\n  if (planType) {\n    credentials.plan_type = planType;\n  }\n\n  const subscriptionExpiresAt = resolveSubscriptionExpiresAt(account);\n  if (subscriptionExpiresAt) {\n    credentials.subscription_expires_at = subscriptionExpiresAt;\n  }\n\n  return credentials;\n}\n\nfunction buildSub2apiApiKeyCredentials(account: CodexAccount): JsonRecord {\n  const apiKey = account.openai_api_key?.trim();\n  if (!apiKey) {\n    throw new Error('SUB2API_API_KEY_MISSING');\n  }\n  return {\n    base_url: account.api_base_url?.trim() || SUB2API_DEFAULT_OPENAI_BASE_URL,\n    api_key: apiKey,\n  };\n}\n\nfunction buildSub2apiExtra(account: CodexAccount): JsonRecord | undefined {\n  const authProvider = resolveAuthProvider(account);\n  const extra: JsonRecord = {};\n  if (authProvider) {\n    extra.auth_provider = authProvider;\n  }\n  if (\n    account.codex_fingerprint_mode &&\n    account.codex_fingerprint_mode !== 'off'\n  ) {\n    extra.codex_fingerprint_mode = account.codex_fingerprint_mode;","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/utils/codexExportFormats.ts#L337-L373","documentation":"buildSub2apiApiKeyCredentials throws SUB2API_API_KEY_MISSING when building sub2api credentials for an API-key account whose openai_api_key is absent or blank. A sub2api API-key account entry cannot exist without an api_key.","triggerScenarios":"Calling toSub2apiAccount on an API-key-type Codex account where openai_api_key is undefined, empty, or whitespace-only.","commonSituations":"Account created as API-key type but key never entered; key cleared during edit; import from a format that did not carry OPENAI_API_KEY.","solutions":["Set the account's openai_api_key before exporting to sub2api","Skip API-key accounts without a key in the export batch","Re-enter the API key in the account editor","Validate keys at import time so incomplete accounts are flagged early"],"exampleFix":"// before\nconst item = toSub2apiAccount(account); // throws SUB2API_API_KEY_MISSING\n// after\nif (account.openai_api_key?.trim()) {\n  const item = toSub2apiAccount(account);\n} else {\n  console.warn('skip account: missing API key');\n}","handlingStrategy":"validation","validationCode":"if (!account.openai_api_key?.trim()) {\n  throw new Error('cannot export: missing openai_api_key');\n}","typeGuard":"function hasApiKey(a: CodexAccount): boolean {\n  return !!a.openai_api_key?.trim();\n}","tryCatchPattern":"try {\n  const item = toSub2apiAccount(account);\n} catch (e) {\n  if ((e as Error).message === 'SUB2API_API_KEY_MISSING') {\n    // prompt user to enter the API key\n  }\n}","preventionTips":["Require openai_api_key when creating API-key accounts","Filter export batches by credential availability","Warn in the UI when an API-key account has an empty key"],"tags":["validation","api-key","missing-field","export"],"backgroundTag":"missing-credential-field","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}