moeru-ai/airi · error
Failed to extract tweet data
Error message
Failed to extract tweet data
What it means
TweetParser.extractTweetData was given a non-null tweet element but returned a falsy value, meaning it could not pull the required fields (author, text, id, timestamp) out of the DOM. This indicates the tweet element matched but its internal structure differs from what the parser expects.
Source
Thrown at integrations/twitter-services/src/core/services/tweet.ts:285
/**
* Gets detailed information about a specific tweet
*/
async function getTweetDetails(tweetId: string): Promise<TweetDetail> {
try {
const page = ctx.page
await page.goto(`${TWITTER_BASE_URL}/i/status/${tweetId}`)
await page.waitForSelector(SELECTORS.TIMELINE.TWEET)
// Get the main tweet element
const tweetElement = await page.$(SELECTORS.TIMELINE.TWEET)
if (!tweetElement) {
throw new Error('Tweet element not found')
}
// Use the TweetParser to extract the main tweet data
const mainTweet = await TweetParser.extractTweetData(page, tweetElement)
if (!mainTweet) {
throw new Error('Failed to extract tweet data')
}
// Check for quoted tweet
let quotedTweet: Tweet | undefined
const quotedTweetElement = await page.$('[data-testid="quotedTweet"]')
if (quotedTweetElement) {
const extractedQuotedTweet = await TweetParser.extractTweetData(page, quotedTweetElement)
if (extractedQuotedTweet) {
quotedTweet = extractedQuotedTweet
}
}
// Get replies by scrolling to load more using reusable scroll logic
const replySelector = '[data-testid="tweet"][aria-labelledby*="reply"]'
// Try to load at least 10 replies (if available)
await scrollToLoadMoreTweets(page, 10, replySelector)
View on GitHub (pinned to 27111382b4)
Solutions
- Update TweetParser's sub-selectors against the current live tweet DOM.
- Ensure the element passed in is a full tweet article, not a quoted/partial fragment.
- Have the parser log which required field failed so the failing selector is identifiable.
- Pin the automation to a stable Twitter surface (e.g. the /i/status/ page) where the layout is most consistent.
Example fix
// before
const mainTweet = await TweetParser.extractTweetData(page, tweetElement)
if (!mainTweet) {
throw new Error('Failed to extract tweet data')
}
// after
const mainTweet = await TweetParser.extractTweetData(page, tweetElement)
if (!mainTweet) {
const html = await page.evaluate(el => el.outerHTML, tweetElement).catch(() => '<unreadable>')
throw new Error(`Failed to extract tweet data; element snapshot: ${html.slice(0, 500)}`)
} Defensive patterns
Strategy: validation
Validate before calling
// sanity-check the element is a full tweet article, not a quoted fragment
const isArticle = await page.evaluate(
el => !!el?.querySelector('[data-testid="tweetText"]') && !!el?.querySelector('[role="link"]'),
tweetElement,
)
if (!isArticle) throw new Error('Element is not a full tweet article') Type guard
function hasTweetData(t: unknown): t is { id: string; text: string; author: unknown } {
return !!t && typeof (t as any).id === 'string' && typeof (t as any).text === 'string'
} Try / catch
const data = await TweetParser.extractTweetData(page, tweetElement)
if (!data) {
// log DOM snapshot for diagnosis, then degrade
return null
} Prevention
- Keep TweetParser selectors versioned and tested against saved HTML fixtures.
- Pass only full tweet article elements to the parser.
- Log which sub-field failed extraction to accelerate fixes.
When it happens
Trigger: Twitter changed the internal layout of a tweet (avatar/username/text spans restructured); the matched element is a retweet header or quoted tweet container rather than a full tweet; a required sub-selector returned nothing so the parser bailed.
Common situations: Parser written against an older DOM layout; extracted element is a quoted tweet partial; new UI variant (e.g. condensed timeline) served to the bot.
Related errors
- Failed to retweet: ${errorToMessage(error)}
- Failed to post tweet: ${errorToMessage(error)}
- Tweet element not found
- Failed to fetch profile for @${username}
- 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/8907b752be669996.
Report an issue: GitHub.