yikart/AiToEarn · warning · BadRequestException
视频发布状态检查超时,请稍后在TikTok应用中查看发布状态
Error message
视频发布状态检查超时,请稍后在TikTok应用中查看发布状态
What it means
Thrown by uploadAndPublishVideo (tiktok.service.ts:590) when the polling loop exhausts maxRetries (default 30 × 2s ≈ 60s) without the status ever reaching SUCCESS/PUBLISHED or FAILED/ERROR. TikTok is still processing the video, or the status endpoint returns an unrecognized status value so the loop never matches.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts:590
updateTime: new Date()
});
throw new BadRequestException(`视频发布失败: ${statusResult.error_message || '未知错误'}`);
}
// 等待指定时间后再次查询
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
if (!finalStatus) {
// 超时仍未完成
await this.pubRecordModel.findByIdAndUpdate(pubRecord._id, {
status: PubStatus.FAIL,
failReason: '检查视频发布状态超时',
updateTime: new Date()
});
throw new BadRequestException('视频发布状态检查超时,请稍后在TikTok应用中查看发布状态');
}
// 更新发布记录为成功状态
const videoId = finalStatus.video_id || finalStatus.id || publish_id;
await this.pubRecordModel.findByIdAndUpdate(pubRecord._id, {
status: PubStatus.RELEASED,
resourceId: videoId,
updateTime: new Date()
});
return {
...finalStatus,
resourceId: videoId,
publish_id,
};
} catch (error) {
this.logger.error('三步式视频上传发布失败:', error.response?.data || error.message);
throw new BadRequestException(`视频上传发布失败: ${error.response?.data?.error?.message || error.message}`);View on GitHub (pinned to d3aa8bea5b)
Solutions
- Increase maxRetries and/or pollInterval when calling uploadAndPublishVideo for large videos.
- Log every statusResult.status value and add the unrecognized values to the terminal-status comparison.
- Treat status as succeeded-if-processed by checking statusResult.data?.status when the payload is nested.
- Make the failure non-fatal: since the video may still publish, return the publish_id and let the caller verify later instead of throwing.
- Implement exponential backoff to cover longer processing windows without more API calls.
Example fix
// before
if (statusResult.status === 'SUCCESS' || statusResult.status === 'PUBLISHED') {
// after
const ok = ['SUCCESS', 'PUBLISHED', 'SENDING', 'FINISH'];
if (ok.includes(statusResult?.status) || statusResult?.data?.status === 'SUCCESS') { Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
function isTerminalStatus(s: any): boolean {
return ['SUCCESS', 'PUBLISHED', 'FAILED', 'ERROR'].includes(String(s?.status ?? '').toUpperCase());
} Try / catch
try {
await tiktokService.uploadAndPublishVideo(token, userId, accountId, buffer, info, 3000, 60);
} catch (e) {
if (e.message.includes('状态检查超时')) {
// publish may still complete: schedule a background job to re-check publish_id later
await queueStatusRecheck(accountId, publishId);
} else throw e;
} Prevention
- Pass larger maxRetries/pollInterval for big files (e.g. 60 retries × 3s).
- Never assume timeout = failure; TikTok may publish minutes later — always re-check.
- Track unrecognized status strings in logs and extend the terminal-status list.
- Store publish_id so late-arriving successes can be reconciled.
When it happens
Trigger: 30 consecutive status polls return a non-terminal status (e.g. 'PROCESSING', 'PUBLISHING', or a different casing/wording the code doesn't recognize), so finalStatus remains null after the while loop.
Common situations: Large videos taking longer than ~60s to process; TikTok changing the status enum values (e.g. returning 'SENDING' or 'FINISH'); the status check succeeding but with status undefined due to response-shape drift; heavy TikTok-side processing queues.
Related errors
- 视频发布失败: ${statusResult.error_message || '未知错误'}
- No response from Gemini
- No subtitle entries in response
- ChannelAuthRefreshTokenMissing
- InvalidWorkLink
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/38b8348111623ea0.
Report an issue: GitHub.