yikart/AiToEarn · error · BadRequestException
直接上传视频失败: ${error.response?.data?.error?.message || error.me
Error message
直接上传视频失败: ${error.response?.data?.error?.message || error.message} What it means
This is the catch-all wrapper in directUploadVideo: any failure while PUT-ing the video (single-shot or 10MB chunks) to TikTok's upload_url — HTTP errors, expired URL, token rejection, network failure — is logged and re-thrown as BadRequestException('直接上传视频失败: ...') at tiktok.service.ts:451. The embedded detail comes from error.response.data.error.message (Axios) or error.message.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts:451
'Content-Type': contentType,
'Content-Length': chunkLength.toString(),
'Content-Range': `bytes ${start}-${end-1}/${totalSize}`,
'Authorization': `Bearer ${accessToken}`
}
})
);
lastResponse = data;
}
return {
publish_id,
...lastResponse?.data,
};
}
} catch (error) {
this.logger.error('直接上传TikTok视频失败:', error.response?.data || error.message);
throw new BadRequestException(`直接上传视频失败: ${error.response?.data?.error?.message || error.message}`);
}
}
/**
* 检查视频发布状态
* @param accessToken 访问令牌
* @param publishId 发布ID
* @returns 发布状态信息
*/
async checkPublishStatus(
accessToken: string,
publishId: string
): Promise<any> {
try {
const { data } = await firstValueFrom(
this.httpService.post(
`${this.apiBaseUrl}/v2/post/publish/status/fetch/`,
{ publish_id: publishId },View on GitHub (pinned to d3aa8bea5b)
Solutions
- Inspect the logged '直接上传TikTok视频失败' body for TikTok's error code; on auth errors re-authorize and restart from the init step.
- Re-run the init call to get a fresh upload_url if the error suggests an expired/invalid URL, then retry.
- Confirm the file is mp4 and within TikTok size limits; convert/transcode if not.
- Add retry-with-backoff for transient network errors (5xx/timeouts) around each PUT, and avoid re-wrapping internal BadRequestExceptions so root causes stay visible.
Example fix
// before
} catch (error) {
this.logger.error('直接上传TikTok视频失败:', error.response?.data || error.message);
throw new BadRequestException(`直接上传视频失败: ${error.response?.data?.error?.message || error.message}`);
}
// after
} catch (error) {
this.logger.error('直接上传TikTok视频失败:', error.response?.data || error.message);
if (error instanceof BadRequestException) throw error;
throw new BadRequestException(`直接上传视频失败: ${error.response?.data?.error?.message || error.message}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!initData?.upload_url) throw new Error('missing upload_url');
const MAX = 2 * 1024 * 1024 * 1024; // check TikTok's documented limit
if (videoBuffer.length > MAX) throw new Error('video exceeds TikTok size limit');
if (!videoBuffer.slice(0, 12).toString('latin1').includes('ftyp')) {
this.logger.warn('videoBuffer may not be a valid MP4');
} Type guard
function isMp4Buffer(v) {
return Buffer.isBuffer(v) && v.length > 11
&& v.readUInt32BE(4) === 0x66747970; // 'ftyp' box
} Try / catch
try {
const result = await directUploadVideo(accessToken, videoBuffer, initData);
} catch (e) {
const detail = /直接上传视频失败: (.*)/.exec(e.message)?.[1] ?? e.message;
if (detail.includes('401') || detail.toLowerCase().includes('unauthorized')) {
// refresh token then re-init and retry
} else if (/expired|invalid.*url/i.test(detail)) {
// re-init for a fresh upload_url
} else throw e;
} Prevention
- Check upload_url freshness right before the PUT; re-init if the gap since init is more than a few minutes.
- Verify access token validity (and environment match) before starting the upload.
- Pre-transcode to mp4 within TikTok limits to avoid mid-upload rejection.
- Distinguish token/URL errors from transient network errors so retries target the right cause.
When it happens
Trigger: Any of: the PUT to upload_url returns 4xx/5xx (expired signature, invalid token, wrong content type), a >10MB video's Content-Range chunk is rejected, connection reset mid-PUT, or the internal missing-field throw from line 387 being re-caught here and re-wrapped.
Common situations: Upload URL TTL expired while preparing a large file, access token expired or wrong environment, TikTok rejecting non-mp4 or oversized files, unstable network on large uploads, and double-wrapping masking the original root cause.
Related errors
- 分片上传视频失败: ${error.response?.data?.error?.message || error.me
- 检查视频发布状态失败: ${error.response?.data?.error?.message || error.
- Relay uploadSign returned no uploadUrl: ${JSON.stringify(sig
- 上传视频失败,失败原因1:
- 交换授权码失败: ${error.response?.data?.error_description || error.
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/872e91e9e45b77e9.
Report an issue: GitHub.