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
- 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
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
- 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
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
- messages.rawLineNoRefreshToken(item.lineNumber)
- 未找到有效 Token {:?}
- 不支持的 JSON 格式 {:?}
- 磁盘空间不足,已终止导入(已成功 {} 个)。{}
- Codex 导入失败 {}: {}
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/f19be2361323d37b.
Report an issue: GitHub.