jackwener/OpenCLI · error · ArgumentError
Resume file source mismatch: expected ${expected.source}, fo
Error message
Resume file source mismatch: expected ${expected.source}, found ${parsed.source || 'unknown'} What it means
When resuming, the `expected` object built by the command carries source: 'bookmarks'. If the resume file's `source` field differs (or is missing), readResumeFile throws this ArgumentError to prevent applying another command's saved state (e.g. likes) to a bookmarks sync.
Source
Thrown at clis/twitter/bookmarks.js:126
let parsed;
try {
parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
}
catch (error) {
throw new CommandExecutionError(`Could not parse Twitter bookmarks resume file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
}
const count = parsed?.count;
const cursor = parsed?.cursor == null ? null : String(parsed.cursor);
const outputFile = parsed?.outputFile ? path.resolve(String(parsed.outputFile)) : null;
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)
|| !Number.isInteger(count) || count < 0
|| (parsed.cursor != null && typeof parsed.cursor !== 'string')
|| (cursor !== null && !cursor.trim())) {
throw new CommandExecutionError(`Twitter bookmarks resume file ${filePath} has an invalid shape`);
}
if (expected) {
if (parsed.source !== expected.source)
throw new ArgumentError(`Resume file source mismatch: expected ${expected.source}, found ${parsed.source || 'unknown'}`);
if (outputFile !== expected.outputFile)
throw new ArgumentError(`Resume file output mismatch: expected ${expected.outputFile || 'in-memory mode'}, found ${outputFile || 'in-memory mode'}`);
if (!expected.outputFile && !Array.isArray(parsed.tweets))
throw new CommandExecutionError(`Twitter bookmarks resume file ${filePath} is missing in-memory tweets`);
if (!expected.outputFile && parsed.tweets.length !== count)
throw new CommandExecutionError(`Twitter bookmarks resume file ${filePath} count does not match its in-memory tweets`);
if (parsed.complete)
throw new CommandExecutionError(`Twitter bookmarks resume file ${filePath} is already marked complete`);
}
return {
cursor,
count,
tweets: Array.isArray(parsed.tweets) ? parsed.tweets : [],
complete: Boolean(parsed.complete),
source: parsed.source || null,
outputFile,
updatedAt: parsed.updatedAt || null,
};View on GitHub (pinned to 49907e53dc)
Solutions
- Use a dedicated resume-file path per command (one for bookmarks, one for likes).
- Delete the mismatched file and start a fresh bookmarks sync.
- If the file is otherwise correct, set `"source": "bookmarks"` (only if you are certain of its origin).
Example fix
// before: resume.json = {"source": "likes", ...}
cli twitter likes --all --resume-file ./likes.json # run with the matching command
// after: bookmarks uses its own file
cli twitter bookmarks --all --resume-file ./bookmarks.json Defensive patterns
Strategy: validation
Validate before calling
const parsed = JSON.parse(fs.readFileSync(resumeFile, 'utf8'));
if (parsed.source !== 'bookmarks') throw new Error('wrong source, use the matching command'); Type guard
function isBookmarksResume(v) {
return typeof v === 'object' && v !== null && v.source === 'bookmarks';
} Try / catch
try {
await run(['twitter', 'bookmarks', '--all', '--resume-file', p]);
} catch (e) {
if (String(e.message).includes('Resume file source mismatch')) {
// use a per-command resume path
await run(['twitter', 'bookmarks', '--all', '--resume-file', 'bookmarks-resume.json']);
} else throw e;
} Prevention
- Use a distinct resume-file path per command (bookmarks vs likes).
- Never copy resume files between commands.
- Check the `source` field before resuming.
- Name files after the command: bookmarks-resume.json.
When it happens
Trigger: Running `twitter bookmarks --all --resume-file <path>` where the file was created by `twitter likes --resume-file <same path>` or another source, or the file's `source` field was deleted in a manual edit.
Common situations: Sharing one resume file path between likes and bookmarks syncs; copying a resume file across commands; stripping fields while reformatting the JSON.
Related errors
- Resume file output mismatch: expected ${expected.outputFile
- Resume file source mismatch: expected ${expected.source}, fo
- Resume file username mismatch: expected @${expected.username
- Resume file output mismatch: expected ${expected.outputFile
- Unknown 12306 station telecode "${trimmed}"
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9e30deb04ba7aa0d.
Report an issue: GitHub.