gitroomhq/postiz-app · error · BadBody
${handleError?.value || ''}
Error message
${handleError?.value || ''} What it means
checkPostStatus sees status === 'FAILED' in the TikTok Business direct-post status body. It runs handleErrors on the reason plus full JSON and throws BadBody with the classified message (or empty string fallback), meaning TikTok definitively rejected the video.
Solutions
- Inspect the logged post JSON - the reason field names the failure cause
- Fix the video (codec/format/content) and re-upload
- If privacy=SELF_ONLY draft, ensure the post completes within the allowed window
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate video before scheduling
const probe = await ffprobe(video);
if (probe.codec !== 'h264' || probe.duration > 600) throw new Error('Video not suitable for TikTok'); Type guard
const isFailedStatus = (s?: string): s is 'FAILED' => s === 'FAILED';
Try / catch
try { await provider.check(post); } catch (e) { if (e instanceof BadBody && /tiktok-business-error-upload/.test(e.error)) markPostFailedWithReason(post, e.error); throw e; } Prevention
- Pre-encode uploads to TikTok-friendly H.264 MP4
- Avoid content likely to trip moderation (music, restricted topics)
- Show the API reason field to end users for actionable feedback
When it happens
Trigger: Direct post fails TikTok's asynchronous review: policy violation, corrupted/unplayable video, privacy setting rejected, or video stuck processing then failed.
Common situations: Videos with copyrighted music, content flagged by moderation, unsupported codecs, or draft posts left beyond TikTok's processing window.
Related errors
- ${handleError?.value || ''}
- ${handleError?.value || 'Failed to upload the video to…
- The media storage did not return the requested byte range…
- ${handleError.value}
- ${handleError?.value || information?.message || 'Could not…
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/2e29a9656911d405.
Report an issue: GitHub.
Appendix: source
Thrown at libraries/nestjs-libraries/src/integrations/social/tiktok.business.provider.ts:500
// post_ids can lag up to 3 minutes behind PUBLISH_COMPLETE, and never
// shows up at all for non-public posts - fall back to the profile URL
// and keep the share_id (postAnalytics resolves it later).
const publicPostId = post_ids?.[0];
return {
status: 'completed',
releaseURL: !publicPostId
? `https://www.tiktok.com/@${integration.profile}`
: `https://www.tiktok.com/@${integration.profile}/video/${publicPostId}`,
postId: !publicPostId ? pendingData.publishId : String(publicPostId),
};
}
if (status === 'FAILED') {
const handleError = this.handleErrors(
`${reason || ''} ${JSON.stringify(post)}`
);
throw new BadBody(
'tiktok-business-error-upload',
JSON.stringify(post),
Buffer.from(JSON.stringify(post)),
handleError?.value || ''
);
}
return { status: 'pending', pendingData };
}
// UPLOAD does not publish - it only drops the media into the user's TikTok
// inbox as a draft - so only an explicit UPLOAD selects it. A missing value
// (drafts, or any caller that skipped the setting) publishes instead of
// silently landing in the inbox.
private contentPostingMethod(
firstPost: PostDetails<TikTokDto>
): TikTokDto['content_posting_method'] {
return firstPost?.settings?.content_posting_method === 'UPLOAD'View on GitHub (pinned to 0f1647f749)