jackwener/OpenCLI · warning · EmptyResultError

Timeline is private or unavailable to the current X account;

Error message

Timeline is private or unavailable to the current X account; completion cannot be proven.

What it means

parseCollectionPage detects private/unavailable timelines via looksLikePrivateTwitterTimeline and throws an EmptyResultError before attempting to parse, because a private timeline yields no parseable page yet completeness of the collection cannot be proven. It signals that the authenticated X account cannot access the target's timeline at all.

Source

Thrown at clis/twitter/collection.js:191

        author,
        name: user?.legacy?.name || user?.core?.name || '',
        text: tweet.note_tweet?.note_tweet_results?.result?.text || legacy.full_text || '',
        likes: legacy.favorite_count || 0,
        retweets: legacy.retweet_count || 0,
        replies: legacy.reply_count || 0,
        views: Number(tweet.views?.count) || 0,
        is_retweet: Boolean(legacy.retweeted_status_result),
        created_at: legacy.created_at || '',
        url: `https://x.com/${author}/status/${tweet.rest_id}`,
        ...extractMedia(legacy),
        quoted_tweet: extractQuotedTweet(tweet),
        relationship: extractRelationship(tweet),
    };
}

function parseCollectionPage(payload, seen) {
    if (looksLikePrivateTwitterTimeline(payload)) {
        throw new EmptyResultError(
            'twitter collection',
            'Timeline is private or unavailable to the current X account; completion cannot be proven.',
        );
    }
    const result = payload?.data?.user?.result;
    if (!result || typeof result !== 'object') {
        throw new CommandExecutionError('twitter_collection_protocol_error: missing UserTweets result');
    }
    const instructionSets = [
        result.timeline_v2?.timeline?.instructions,
        result.timeline?.timeline?.instructions,
    ].filter(Array.isArray);
    if (instructionSets.length === 0) {
        throw new CommandExecutionError(
            'twitter_collection_protocol_error: missing UserTweets timeline instructions',
        );
    }
    const posts = [];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Authenticate as an X account that follows the private account (or confirm you're logged in as the intended user)
  2. Verify the target handle is still active and public in a browser
  3. Re-authenticate / refresh tokens if you believe you do have access
  4. If the account is legitimately inaccessible, treat it as an empty result and stop — completion cannot be proven
Defensive patterns

Strategy: try-catch

Validate before calling

function timelineLooksPrivate(payload) {
  return looksLikePrivateTwitterTimeline(payload); // pre-check the same heuristic the CLI uses
}
// before collecting:
if (timelineLooksPrivate(payload)) console.warn('target timeline is private/unavailable; aborting');

Type guard

function isAccessibleTimeline(payload) {
  return !looksLikePrivateTwitterTimeline(payload)
    && payload?.data?.user?.result != null
    && typeof payload.data.user.result === 'object';
}

Try / catch

try {
  const posts = await collectTimeline(handle, { until, limit });
} catch (err) {
  if (String(err.message).includes('private or unavailable')) {
    console.warn(`${handle}: timeline inaccessible to current account; skipping`);
  } else throw err;
}

Prevention

When it happens

Trigger: Requesting a user timeline whose payload matches the private-timeline heuristics — the target account is protected/private, suspended, blocked you, or the GraphQL response contains the standard unavailability structure.

Common situations: Collecting from a protected account you don't follow; account went private or was suspended mid-archive; authenticating with the wrong X account that lacks access; geo/withheld restrictions on the target.

Related errors


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