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.

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.

Appendix: 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)