moeru-ai/airi · error
Failed to search tweets: ${errorToMessage(error)}
Error message
Failed to search tweets: ${errorToMessage(error)} What it means
Thrown by searchTweets as a catch-all wrapper: any error thrown inside the function (page.goto failure, waitForSelector timeout, TweetParser failure, tab click errors) is caught, logged to console.error, and re-thrown as a new Error whose message prefixes the original via errorToMessage. The original cause is not preserved on .cause, only stringified into the message.
Source
Thrown at integrations/twitter-services/src/core/services/tweet.ts:102
}
}
// Wait for content to load after filter change
await page.waitForSelector(SELECTORS.TIMELINE.TWEET)
// Use the TweetParser to extract tweets
let tweets = await TweetParser.parseTimelineTweets(page)
// Limit tweets to count if specified
if (options.count && options.count > 0) {
tweets = tweets.slice(0, options.count)
}
return tweets
}
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 likedView on GitHub (pinned to 27111382b4)
Solutions
- Inspect the wrapped message (errorToMessage output) — a waitForSelector timeout points to stale selectors or a login wall; a navigation error points to connectivity.
- Update SELECTORS.TIMELINE.TWEET and SEARCH.* selectors to match the current X DOM.
- Re-authenticate / refresh cookies so the session is logged in before searching.
- Add retry with backoff for transient network/rate-limit failures.
Example fix
// before
async function searchTweets(query, options) {
try { /* ... navigate + parse ... */ return tweets }
catch (error) {
console.error('Error searching tweets:', error)
throw new Error(`Failed to search tweets: ${errorToMessage(error)}`)
}
}
// after — preserve cause and add a retry
async function searchTweets(query, options) {
for (let attempt = 0; attempt < 2; attempt++) {
try { /* ... navigate + parse ... */ return tweets }
catch (error) {
if (attempt === 1) throw new Error(`Failed to search tweets: ${errorToMessage(error)}`, { cause: error })
await sleep(1000)
}
}
} Defensive patterns
Strategy: retry
Type guard
function isSearchTweetsError(e: unknown): boolean {
return e instanceof Error && /Failed to search tweets:/.test(e.message)
} Try / catch
for (let attempt = 0; attempt < 3; attempt++) {
try {
return await tweetServices.tweet.searchTweets(query)
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
if (/waitForSelector|timeout|net::/i.test(msg) && attempt < 2) {
await sleep(1500 * (attempt + 1))
continue
}
throw e
}
} Prevention
- Keep SELECTORS in sync with the current X DOM to avoid waitForSelector timeouts.
- Maintain an authenticated session so the search page renders results, not a login wall.
- Retry with backoff for transient network or rate-limit failures.
- Preserve the original cause via the Error options bag for easier diagnosis.
When it happens
Trigger: The Puppeteer page navigates to the search URL and a step throws: network/navigation error on page.goto; SELECTORS.TIMELINE.TWEET never appears (waitForSelector timeout) due to a login wall or layout change; the filter tab selector is stale; TweetParser.parseTimelineTweets throws on unexpected DOM.
Common situations: Twitter/X changed its DOM so SELECTORS are stale; session/cookies expired showing a login prompt instead of results; rate limiting or temporary block shows an interstitial; the headless browser lost connectivity; the query returned zero results and the parser expected a tweet node.
Related errors
- Failed to like tweet: ${errorToMessage(error)}
- Like button not found
- Retweet button not found
- Search query is empty. Please provide a query to search.
- Tweet text is empty. Please provide text to post.
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/9f8c9c27a7c89479.
Report an issue: GitHub.