jlcodes99/cockpit-tools · error

messages.rawLineMultipleRefreshTokens(item.lineNumber)

Error message

messages.rawLineMultipleRefreshTokens(item.lineNumber)

What it means

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.

Source

Thrown at src/hooks/useProviderAccountsPage.ts:339

const parseCodexRawRefreshTokenItems = (
  rawContent: string,
  messages: ExternalImportBundleParseMessages,
): unknown[] | null => {
  const lines = rawContent
    .split(/\r?\n/)
    .map((line, index) => ({ line: line.trim(), lineNumber: index + 1 }))
    .filter((item) => item.line.length > 0);

  if (lines.length === 0) return null;

  const items: unknown[] = [];
  for (const item of lines) {
    const matches = [...item.line.matchAll(CODEX_REFRESH_TOKEN_PATTERN)];
    if (matches.length === 0) {
      throw new Error(messages.rawLineNoRefreshToken(item.lineNumber));
    }
    if (matches.length > 1) {
      throw new Error(messages.rawLineMultipleRefreshTokens(item.lineNumber));
    }

    const match = matches[0];
    const refreshToken = match[0].trim();
    const accountNote = item.line.slice(0, match.index ?? 0).trim();
    items.push({
      refresh_token: refreshToken,
      ...(accountNote ? { account_note: accountNote } : {}),
    });
  }

  return items.length > 0 ? items : null;
};

const resolveExternalImportBundleItems = (
  rawContent: string,
  platformId: string,
  messages: ExternalImportBundleParseMessages,

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Split the line so each refresh token sits on its own line
  2. Remove the extra rt_... substring that is not the account refresh token
  3. If a secondary credential contains rt_ text, rename/redact it or move it into a JSON object's named field instead of raw text

Example fix

// before (two tokens on one line)
rt_abc123 rt_def456
// after
rt_abc123
rt_def456
Defensive patterns

Strategy: validation

Validate before calling

const CODEX_TOKEN = /rt_[A-Za-z0-9._-]+/g;
const dup = content.split(/\r?\n/)
  .map((l, i) => ({ l: l.trim(), n: i + 1 }))
  .filter(x => x.l && [...x.l.matchAll(CODEX_TOKEN)].length > 1);
if (dup.length) throw new Error(`Line(s) ${dup.map(d => d.n).join(',')} contain multiple rt_ tokens; split them`);

Type guard

const hasExactlyOneToken = (line: string): boolean =>
  [...line.matchAll(/rt_[A-Za-z0-9._-]+/g)].length === 1;

Try / catch

try {
  items = resolveExternalImportBundleItems(content, 'codex', messages);
} catch (e) {
  if (e instanceof Error && /multiple refresh tokens/i.test(e.message)) {
    promptSplitLine(e.message);
  }
}

Prevention

When it happens

Trigger: platformId is 'codex', JSON and line-delimited parsing failed, and one non-empty line contains two or more rt_[A-Za-z0-9._-]+ substrings.

Common situations: 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.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/f19be2361323d37b. Report an issue: GitHub.