jackwener/OpenCLI · error · CommandExecutionError

twitter_likes_archive_incomplete

twitter_likes_archive_incomplete

Error message

twitter_likes_archive_incomplete: stopped after ${pages} page(s); completion cannot be proven

What it means

A CommandExecutionError (code `twitter_likes_archive_incomplete`) thrown when --fetch-all was requested but the pagination loop stopped without proving the timeline was exhausted (exhausted === false). Since completion cannot be proven, the command refuses to return a partial archive; it preserves the resume file so a later run can continue.

Source

Thrown at clis/twitter/likes.js:372

        }
        // Resume is only removed after the timeline is truly exhausted. Hitting
        // --max-pages, partial API errors after some rows, or an interrupt must
        // leave the resume file so the next run can continue.
        if (exhausted)
            removeResumeFile(resumeFile);
        if (useOutputFile) {
            return {
                outputFile,
                count: outputCount,
                source: 'likes',
                username,
                complete: exhausted,
                pages,
                ...(exhausted ? {} : { cursor, resumeFile: resumeFile || null }),
            };
        }
        if (fetchAll && !exhausted) {
            throw new CommandExecutionError(
                `twitter_likes_archive_incomplete: stopped after ${pages} page(s); completion cannot be proven`,
                resumeFile ? `Resume with --resume-file ${resumeFile}` : 'Rerun with --resume-file to preserve continuation state.',
            );
        }
        const trimmed = fetchAll ? allTweets : allTweets.slice(0, limit);
        return applyTopByEngagement(trimmed, topByEngagement);
    },
});
export const __test__ = {
    sanitizeQueryId,
    buildLikesUrl,
    parseLikes,
    readResumeFile,
};

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Rerun with the suggested --resume-file path printed in the remediation to continue from the saved cursor.
  2. Increase --max-pages (or remove it) so the timeline can be fully drained.
  3. Retry after a transient API failure — the resume file preserves progress, so no rows are lost.
  4. If a partial archive is acceptable, drop --fetch-all so the command returns fetched rows with an explicit incomplete marker instead of throwing.

Example fix

// before
opencli twitter likes alice --fetch-all --max-pages 5
// after: continue to completion
opencli twitter likes alice --fetch-all --resume-file /tmp/twitter-likes-alice.resume.json
Defensive patterns

Strategy: retry

Validate before calling

// ensure generous page budget before --fetch-all
const expectedMax = knownLikesCount ? Math.ceil(knownLikesCount / 20) + 5 : 100;
if (maxPages < expectedMax) console.warn(`--max-pages ${maxPages} may not cover ~${expectedMax} pages; keep --resume-file`);

Try / catch

try {
  const archive = await cli.run(['twitter', 'likes', user, '--fetch-all']);
} catch (e) {
  if (String(e.message).startsWith('twitter_likes_archive_incomplete')) {
    const resumeFile = /--resume-file (\S+)/.exec(e.message)?.[1];
    // rerun continuing from the saved cursor
    return cli.run(['twitter', 'likes', user, '--fetch-all', '--resume-file', resumeFile]);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running the likes command with fetchAll=true and the loop ends via --max-pages, a mid-run API error after some pages, or an interrupt, while a cursor still exists. The error message names how many pages were fetched and points at the resume file.

Common situations: Hitting the --max-pages cap during a large backfill; transient GraphQL failures partway through; killing the process with Ctrl-C during a long archive run.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/595032fc75147ae9. Report an issue: GitHub.