jackwener/OpenCLI · error · CommandExecutionError
Could not persist Twitter likes resume state: ${error instan
Error message
Could not persist Twitter likes resume state: ${error instanceof Error ? error.message : String(error)} What it means
writeResumeFile persists resume state atomically via a temporary file that is later renamed over the target. If any filesystem operation (write, rename, mkdir) fails, the temp file is removed and the original error message is wrapped in a CommandExecutionError with this prefix. It signals the run's progress could not be saved to disk and the underlying OS error is embedded in the message.
Source
Thrown at clis/twitter/likes.js:182
// Keep this in sync with twitter/bookmarks; wording is command-specific, so the
// atomic tmp-write/rename cleanup sequence intentionally remains local.
function writeResumeFile(filePath, payload) {
if (!filePath)
return;
ensureParentDir(filePath);
const temporaryPath = `${filePath}.tmp-${process.pid}`;
try {
fs.writeFileSync(temporaryPath, JSON.stringify(payload, null, 2) + '\n');
fs.renameSync(temporaryPath, filePath);
}
catch (error) {
try {
fs.rmSync(temporaryPath, { force: true });
}
catch {
}
throw new CommandExecutionError(`Could not persist Twitter likes resume state: ${error instanceof Error ? error.message : String(error)}`);
}
}
cli({
site: 'twitter',
name: 'likes',
access: 'read',
description: 'Fetch liked tweets of a Twitter user (defaults to the logged-in user when no username is given)',
domain: 'x.com',
strategy: Strategy.COOKIE,
browser: true,
args: [
{ name: 'username', type: 'string', positional: true, help: 'Twitter screen name (with or without @). Defaults to the logged-in user when omitted.' },
{ name: 'limit', type: 'int', default: 20, help: 'Maximum number of liked tweets to return (default 20). Ignored when --all is set.' },
{ name: 'all', type: 'bool', default: false, help: 'Fetch all liked-tweet pages until exhausted. Prefer --output-file for large archives.' },
{ name: 'resume-file', type: 'string', help: 'Resume file for long-running all-pages likes syncs.' },
{ name: 'output-file', type: 'string', help: 'Write all-page results to JSONL. Requires --all and --resume-file.' },
{ name: 'max-pages', type: 'int', help: `Optional pagination safety cap (default ${DEFAULT_MAX_PAGINATION_PAGES}; raised automatically with --all).` },
{ name: 'top-by-engagement', type: 'int', default: 0, help: 'When set to N>0, re-rank the liked tweets by weighted engagement (likes×1 + retweets×3 + replies×2 + bookmarks×5 + log10(views+1)×0.5) and return the top N. Default 0 keeps the API\'s native (recency) ordering. Incompatible with --output-file.' },View on GitHub (pinned to 49907e53dc)
Solutions
- Read the embedded OS error after the colon and fix it — e.g. create the parent directory (mkdir -p) the resume file path expects.
- Check free disk space (df -h) and quotas; clear space if ENOSPC.
- Verify the volume is writable (permissions, not mounted read-only) and the user running the CLI can write there.
- Point --resume-file at a local writable path instead of a network mount, then move it after the run.
Example fix
// before opencli twitter likes @jack --all --resume-file /nonexistent/dir/likes.json --output-file likes.ndjson // after mkdir -p ./resume && opencli twitter likes @jack --all --resume-file ./resume/likes.json --output-file likes.ndjson
Defensive patterns
Strategy: try-catch
Validate before calling
const dir = path.dirname(resumePath);
fs.mkdirSync(dir, { recursive: true });
fs.accessSync(dir, fs.constants.W_OK); Try / catch
try {
await runLikes({ resumeFile });
} catch (err) {
if (/Could not persist Twitter likes resume state/.test(err.message)) {
const cause = err.message.split(': ')[1];
console.error('Resume persist failed:', cause); // e.g. ENOSPC, EACCES
// fix disk/permissions, then resume from the last valid file
}
} Prevention
- Pre-create the resume file's parent directory and confirm writability before long runs.
- Monitor free disk space for full-archive jobs; resume files grow with the archive.
- Use local disk for resume files, not read-only or flaky network mounts.
When it happens
Trigger: Calling --resume-file whose parent directory does not exist or is not writable; disk full; the temp file cannot be created/renamed due to permissions (read-only volume, EACCES, ENOSPC, EROFS); the path points at a directory.
Common situations: Typo in the resume file path's directory; running in a container with a read-only filesystem; disk quota exceeded on long full-archive scrapes; SMB/NFS mount dropped mid-run.
Related errors
- Short read on part ${partNumber}: expected ${chunkSize} byte
- Could not write Midjourney image ${filePath}: ${errorMessage
- Could not write Midjourney media ${filePath}: ${errorMessage
- Could not persist Twitter bookmarks resume state: ${error in
- Verify command returned no metric for baseline
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/76aff50b230be529.
Report an issue: GitHub.