yikart/AiToEarn · error · BadRequestException
无效的视频上传结果,缺少视频ID
Error message
无效的视频上传结果,缺少视频ID
What it means
Thrown by publishVideo (tiktok.service.ts:631) when the uploadResult passed in contains neither video_id nor init_data.video_id. publishVideo is step two of the legacy publish flow: it needs the video id produced by the upload step to attach to the /v2/video/publish/ call. An uploadResult missing these fields means the preceding upload did not actually yield a usable video.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts:631
* 发布视频(原始方式)
* @param accessToken 访问令牌
* @param userId 用户ID
* @param accountId TikTok账号ID
* @param videoDto 视频发布参数
* @param uploadResult 上传结果,包含视频ID和初始化数据
* @returns 发布结果
*/
async publishVideo(
accessToken: string,
userId: string,
accountId: string,
videoDto: CreateVideoDto,
uploadResult: any
): Promise<any> {
try {
const videoId = uploadResult.video_id || (uploadResult.init_data?.video_id);
if (!videoId) {
throw new BadRequestException('无效的视频上传结果,缺少视频ID');
}
const params: any = {
video_id: videoId,
text: videoDto.description,
disable_comment: false,
disable_duet: false,
privacy_level: videoDto.private ? 'private' : 'public'
};
if (videoDto.hashtags && videoDto.hashtags.length > 0) {
// 添加话题标签
const hashtags = videoDto.hashtags.map(tag => `#${tag.replace(/^#/, '')}`).join(' ');
params.text = `${params.text} ${hashtags}`;
}
// 如果有初始化数据,添加必要的发布参数
if (uploadResult.init_data && uploadResult.init_data.publish_params) {View on GitHub (pinned to d3aa8bea5b)
Solutions
- Inspect the actual uploadResult object (log it) to find where the video id really lives and pass that shape.
- Ensure you pass response.data of the upload call, not the Axios response wrapper.
- Check the upload step's success status before calling publishVideo; abort if it reported failure.
- Align the upload method with the legacy flow expected by publishVideo, or switch entirely to the three-step uploadAndPublishVideo.
- Validate uploadResult in the caller before invoking publishVideo to fail earlier with a clearer message.
Example fix
// before
await tiktokService.publishVideo(token, userId, accountId, dto, uploadResponse);
// after
const uploadData = uploadResponse?.data?.data ?? uploadResponse?.data;
if (!uploadData?.video_id && !uploadData?.init_data?.video_id) {
throw new Error(`upload returned no video_id: ${JSON.stringify(uploadData)}`);
}
await tiktokService.publishVideo(token, userId, accountId, dto, uploadData); Defensive patterns
Strategy: type-guard
Validate before calling
const vid = uploadResult?.video_id ?? uploadResult?.init_data?.video_id;
if (!vid) {
throw new Error(`no video_id in upload result: ${JSON.stringify(uploadResult)}`);
} Type guard
function hasVideoId(r: unknown): r is { video_id?: string; init_data?: { video_id: string } } {
const o = r as any;
return typeof o?.video_id === 'string' && o.video_id.length > 0
|| typeof o?.init_data?.video_id === 'string' && o.init_data.video_id.length > 0;
} Try / catch
try {
await tiktokService.publishVideo(token, userId, accountId, dto, uploadResult);
} catch (e) {
if (e.message.includes('缺少视频ID')) {
logger.error('upload result shape mismatch', uploadResult);
// fix normalization of the upload response, then retry
} else throw e;
} Prevention
- Normalize upload responses (unwrap Axios .data) before passing to publishVideo.
- Keep upload and publish steps from the same API generation — don't mix three-step and legacy flows.
- Unit-test the upload response shape against a recorded fixture.
- Fail fast in the caller when the upload step reported an error instead of swallowing it.
When it happens
Trigger: Caller passes the raw response of a failed or differently-shaped upload (e.g. { success: true } with no data, or a direct-upload response whose id lives under data.data.video_id), so uploadResult.video_id and uploadResult.init_data?.video_id are both undefined.
Common situations: Mixing responses between the new three-step API and the legacy upload flow; passing the whole Axios response instead of response.data; upload actually failed upstream but its error was swallowed; TikTok response-shape changes nesting video_id differently.
Related errors
- 初始化失败,缺少必要的上传参数
- No subtitle entries in response
- ResponseCode.ChannelAccountCreateRequiredFieldMissing
- InvalidWorkLink
- userId是必需的
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/38ee0f0cb6967632.
Report an issue: GitHub.