moeru-ai/airi · error

Like button not found

Error message

Like button not found

What it means

Thrown by likeTweet when page.$(SELECTORS.TIMELINE.LIKE_BUTTON) returns null — after the tweet page loaded (waitForSelector for the tweet passed) but the like button element was not found in the DOM. This is a plain Error, distinct from the surrounding catch-all (it is thrown inside the try, so it gets re-wrapped by the 'Failed to like tweet' catch).

Source

Thrown at integrations/twitter-services/src/core/services/tweet.ts:117

    }
    catch (error: unknown) {
      console.error('Error searching tweets:', error)
      throw new Error(`Failed to search tweets: ${errorToMessage(error)}`)
    }
  }

  /**
   * Likes a tweet with the given ID
   */
  async function likeTweet(tweetId: string): Promise<boolean> {
    try {
      const page = ctx.page
      await page.goto(`${TWITTER_BASE_URL}/i/status/${tweetId}`)
      await page.waitForSelector(SELECTORS.TIMELINE.TWEET)

      const likeButton = await page.$(SELECTORS.TIMELINE.LIKE_BUTTON)
      if (!likeButton) {
        throw new Error('Like button not found')
      }

      // Check if already liked
      const isAlreadyLiked = await page.$eval(
        SELECTORS.TIMELINE.LIKE_BUTTON,
        el => el.getAttribute('aria-pressed') === 'true',
      )

      if (!isAlreadyLiked) {
        await likeButton.click()
        // Wait for the like to register
        await page.waitForFunction(
          `document.querySelector('${SELECTORS.TIMELINE.LIKE_BUTTON}')?.getAttribute('aria-pressed') === 'true'`,
          { timeout: 5000 },
        )
      }

      return true

View on GitHub (pinned to 27111382b4)

Solutions

  1. Update SELECTORS.TIMELINE.LIKE_BUTTON to the current X data-testid (commonly '[data-testid="like"]').
  2. Verify the tweetId resolves to an existing, viewable tweet.
  3. Ensure the session is authenticated and the tweet is not protected/age-restricted.
  4. Re-query the button with a short waitForSelector(LIKE_BUTTON) before page.$ to handle render lag.

Example fix

// before
const likeButton = await page.$(SELECTORS.TIMELINE.LIKE_BUTTON)
if (!likeButton) {
  throw new Error('Like button not found')
}

// after — wait for the button and confirm the tweet is viewable
await page.waitForSelector(SELECTORS.TIMELINE.LIKE_BUTTON, { timeout: 5000 })
const likeButton = await page.$(SELECTORS.TIMELINE.LIKE_BUTTON)
if (!likeButton) {
  throw new Error('Like button not found (tweet may be unavailable)')
}
Defensive patterns

Strategy: validation

Validate before calling

await page.waitForSelector(SELECTORS.TIMELINE.LIKE_BUTTON, { timeout: 5000 })
const likeButton = await page.$(SELECTORS.TIMELINE.LIKE_BUTTON)
if (!likeButton) throw new Error('Like button not found (tweet may be unavailable)')

Type guard

function isLikeButtonNotFoundError(e: unknown): boolean {
  // Note: likeTweet wraps this into 'Failed to like tweet: Like button not found'
  return e instanceof Error && /Like button not found/.test(e.message)
}

Try / catch

try {
  await tweetServices.tweet.likeTweet(tweetId)
} catch (e) {
  if (e instanceof Error && /Like button not found/.test(e.message)) {
    // update SELECTORS.TIMELINE.LIKE_BUTTON or verify the tweet is viewable
  } else throw e
}

Prevention

When it happens

Trigger: Navigating to /i/status/<tweetId> where the tweet node renders but the like-button selector does not match: SELECTORS.TIMELINE.LIKE_BUTTON is stale after an X UI change; the tweet is protected/deleted so the action row is absent; the page shows a 'This post is unavailable' state; ARIA/aria-pressed attribute moved to a nested element.

Common situations: X redesigned the action bar so the data-testid/selector changed; tweet id is invalid or belongs to a deleted/protected post; the logged-in session lacks permission to see the action row; slow render meant the button existed but page.$ ran before paint (rare, since waitForSelector for TWEET already passed).

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/a35af2dc1afa3772. Report an issue: GitHub.