{"record":{"id":"f19be2361323d37b","repo":"jlcodes99/cockpit-tools","slug":"messages-rawlinemultiplerefreshtokens-item-linenum","errorCode":null,"errorMessage":"messages.rawLineMultipleRefreshTokens(item.lineNumber)","messagePattern":"messages\\.rawLineMultipleRefreshTokens\\(item\\.lineNumber\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/hooks/useProviderAccountsPage.ts","lineNumber":339,"sourceCode":"const parseCodexRawRefreshTokenItems = (\n  rawContent: string,\n  messages: ExternalImportBundleParseMessages,\n): unknown[] | null => {\n  const lines = rawContent\n    .split(/\\r?\\n/)\n    .map((line, index) => ({ line: line.trim(), lineNumber: index + 1 }))\n    .filter((item) => item.line.length > 0);\n\n  if (lines.length === 0) return null;\n\n  const items: unknown[] = [];\n  for (const item of lines) {\n    const matches = [...item.line.matchAll(CODEX_REFRESH_TOKEN_PATTERN)];\n    if (matches.length === 0) {\n      throw new Error(messages.rawLineNoRefreshToken(item.lineNumber));\n    }\n    if (matches.length > 1) {\n      throw new Error(messages.rawLineMultipleRefreshTokens(item.lineNumber));\n    }\n\n    const match = matches[0];\n    const refreshToken = match[0].trim();\n    const accountNote = item.line.slice(0, match.index ?? 0).trim();\n    items.push({\n      refresh_token: refreshToken,\n      ...(accountNote ? { account_note: accountNote } : {}),\n    });\n  }\n\n  return items.length > 0 ? items : null;\n};\n\nconst resolveExternalImportBundleItems = (\n  rawContent: string,\n  platformId: string,\n  messages: ExternalImportBundleParseMessages,","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/hooks/useProviderAccountsPage.ts#L321-L357","documentation":"For codex raw-text import, each line must contain exactly one refresh token. This error (line 339) is thrown when a single line matches the /rt_.../ pattern more than once, making it ambiguous which token is the account's refresh token.","triggerScenarios":"platformId is 'codex', JSON and line-delimited parsing failed, and one non-empty line contains two or more rt_[A-Za-z0-9._-]+ substrings.","commonSituations":"Pasting two accounts' tokens on one line; a line containing both a refresh token and another rt_-prefixed credential (e.g. session or API token); concatenated exports with tokens separated only by spaces.","solutions":["Split the line so each refresh token sits on its own line","Remove the extra rt_... substring that is not the account refresh token","If a secondary credential contains rt_ text, rename/redact it or move it into a JSON object's named field instead of raw text"],"exampleFix":"// before (two tokens on one line)\nrt_abc123 rt_def456\n// after\nrt_abc123\nrt_def456","handlingStrategy":"validation","validationCode":"const CODEX_TOKEN = /rt_[A-Za-z0-9._-]+/g;\nconst dup = content.split(/\\r?\\n/)\n  .map((l, i) => ({ l: l.trim(), n: i + 1 }))\n  .filter(x => x.l && [...x.l.matchAll(CODEX_TOKEN)].length > 1);\nif (dup.length) throw new Error(`Line(s) ${dup.map(d => d.n).join(',')} contain multiple rt_ tokens; split them`);","typeGuard":"const hasExactlyOneToken = (line: string): boolean =>\n  [...line.matchAll(/rt_[A-Za-z0-9._-]+/g)].length === 1;","tryCatchPattern":"try {\n  items = resolveExternalImportBundleItems(content, 'codex', messages);\n} catch (e) {\n  if (e instanceof Error && /multiple refresh tokens/i.test(e.message)) {\n    promptSplitLine(e.message);\n  }\n}","preventionTips":["Never place two tokens on the same line","Keep non-refresh rt_-prefixed credentials out of raw import text","Split multi-account pastes so each token has its own line"],"tags":["codex","import","ambiguity","refresh-token"],"backgroundTag":"ambiguous-refresh-token","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"}