yikart/AiToEarn · error · TwitterPlatformException
Twitter post id missing
Error message
Twitter post id missing
What it means
createPost submits a tweet via POST /2/tweets through a wrapped client call, then reads response.data?.id. If the platform response lacks a string id, TwitterPlatformException('Twitter post id missing') is thrown because the library cannot return a valid postId/permalink.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/twitter/twitter.service.ts:241
text: params.text,
...(params.mediaIds?.length ? { media: { media_ids: params.mediaIds } } : {}),
...(params.replyTo ? { reply: { in_reply_to_tweet_id: params.replyTo } } : {}),
...(params.quoteTweetId ? { quote_tweet_id: params.quoteTweetId } : {}),
...(params.replySettings ? { reply_settings: params.replySettings } : {}),
...(params.poll ? { poll: params.poll } : {}),
made_with_ai: params.madeWithAi,
paid_partnership: params.paidPartnership,
}
const response = await this.runApiClientOperation<TwitterPostResponse>({
accessToken,
endpoint: 'POST /2/tweets',
context: { accountId: params.accountId },
call: client => client.posts.create(body),
})
const postId = response.data?.id
if (typeof postId !== 'string') {
throw new TwitterPlatformException('Twitter post id missing')
}
return {
postId,
permalink: `https://x.com/i/status/${postId}`,
}
}
async deletePost(accessToken: string, postId: string, accountId?: string): Promise<boolean> {
await this.runApiClientOperation({
accessToken,
endpoint: 'DELETE /2/tweets/:id',
context: { accountId, platformWorkId: postId },
call: client => client.posts.delete(postId),
})
return true
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Log the full raw response of POST /2/tweets when id is missing to see platform errors
- Check for twitter ApiResponseError handling in the client wrapper (raise non-2xx as platform errors)
- Verify twitter-api-v2 client version matches the expected response shape (data.id)
- Retry createPost only after confirming the tweet was not actually created (check for duplicates)
Example fix
// before
const postId = response.data?.id
if (typeof postId !== 'string') {
throw new TwitterPlatformException('Twitter post id missing')
}
// after
const postId = response.data?.id
if (typeof postId !== 'string') {
this.logger.error(`POST /2/tweets missing id, raw=${JSON.stringify(response)}`)
throw new TwitterPlatformException('Twitter post id missing')
} Defensive patterns
Strategy: type-guard
Validate before calling
const body = { text: content.slice(0, 280) }
if (!body.text) throw new Error('tweet text required before createPost') Type guard
function hasPostId(r: unknown): r is { data: { id: string } } {
return !!r && typeof r === 'object' && typeof (r as any).data?.id === 'string'
} Try / catch
try {
const res = await twitterService.createPost(params)
} catch (e) {
if (String(e?.message).includes('post id missing')) {
logger.error('tweet created but id missing; verify manually before retrying', { params })
}
throw e
} Prevention
- Avoid blind retries after createPost — the tweet may exist without an id returned
- Keep the twitter-api-v2 client version aligned with the response unwrapping logic
- Log raw responses on failure
- Deduplicate tweet content to avoid silent platform rejections
When it happens
Trigger: POST /2/tweets returns 200 with an unexpected/empty body, the response wrapper nests the tweet under a different key, or the request actually failed silently (e.g. duplicate tweet, rate limit) while the wrapper still resolves.
Common situations: Duplicate content rejected silently by Twitter, Twitter API version change altering response shape, client wrapper swallowing errors and returning empty data.
Related errors
- Twitter media id missing
- DashScope task id is missing
- ChannelPlatformResponseInvalid
- ChannelAuthRefreshTokenMissing
- ChannelPlatformMediaProcessingTimeout
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/2c414b0c05133042.
Report an issue: GitHub.