jackwener/OpenCLI · error · CommandExecutionError

Could not resolve article ${tweetId} to a tweet ID. The arti

Error message

Could not resolve article ${tweetId} to a tweet ID. The article page may not contain a linked tweet.

What it means

The twitter article command resolves an X article (long-form post) to its linked tweet before fetching it. An in-page script attempts to extract the tweet id from the article page; if the resolved id is missing or not a string, a CommandExecutionError is thrown because X articles do not always embed a tweet link. The command can only proceed when a concrete tweet id exists.

Source

Thrown at clis/twitter/article.js:53

            await page.wait(3);
            const resolvedId = await page.evaluate(`
        (function() {
          var links = document.querySelectorAll('a[href*="/status/"]');
          for (var i = 0; i < links.length; i++) {
            var m = links[i].href.match(/\\/status\\/(\\d+)/);
            if (m) return m[1];
          }
          var og = document.querySelector('meta[property="og:url"]');
          if (og && og.content) {
            var m2 = og.content.match(/\\/status\\/(\\d+)/);
            if (m2) return m2[1];
          }
          return null;
        })()
      `);
            const resolvedTweetId = unwrapBrowserResult(resolvedId);
            if (!resolvedTweetId || typeof resolvedTweetId !== 'string') {
                throw new CommandExecutionError(`Could not resolve article ${tweetId} to a tweet ID. The article page may not contain a linked tweet.`);
            }
            tweetId = resolvedTweetId;
        }
        // Navigate to the tweet page for cookie context
        await page.goto(`https://x.com/i/status/${tweetId}`);
        await page.wait(3);
        // Read CSRF token directly from the cookie store via CDP — zero page.evaluate round-trip
        const cookies = await page.getCookies({ url: 'https://x.com' });
        const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;
        if (!ct0)
            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
        const queryId = await resolveTwitterQueryId(page, 'TweetResultByRestId', TWEET_RESULT_BY_REST_ID_QUERY_ID);
        const rawResult = unwrapBrowserResult(await page.evaluate(`
      async () => {
        const tweetId = ${JSON.stringify(tweetId)};
        const ct0 = ${JSON.stringify(ct0)};

        const bearer = ${JSON.stringify(TWITTER_BEARER_TOKEN)};

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the article actually contains a linked tweet (open it on x.com and check)
  2. Re-check the article id/tweetId argument for typos or truncation
  3. Retry later if X's page markup changed — adapter query scripts may need updating upstream
  4. If a tweet link exists but isn't found, report/update resolveTwitterQueryId scripts or extract the id manually and use the tweet command
Defensive patterns

Strategy: try-catch

Type guard

function resolvedTweetIdIsUsable(v) { return typeof v === 'string' && v.length > 0 && /^\d+$/.test(v); }

Try / catch

try {
  await articleCmd({ tweetId });
} catch (err) {
  if (err.message.includes('Could not resolve article')) {
    console.error('Article has no linked tweet — open it on x.com to verify, or pass the tweet id directly');
  } else throw err;
}

Prevention

When it happens

Trigger: Passing an article id whose page's DOM/state does not contain a linked tweet — the browser evaluate returns null or a non-string and the guard rejects it.

Common situations: Articles that are pure long-form posts with no embedded tweet, X rendering changes that move/remove the tweet link, deleting the associated tweet after the article was published, or passing a truncated/incorrect article id.

Related errors


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