yikart/AiToEarn · error · BadRequestException
初始化响应缺少 publish_id 或 upload_url
Error message
初始化响应缺少 publish_id 或 upload_url
What it means
uploadVideoChunked validates the TikTok video-upload initialization response before sending chunks. TikTok's PULL/FILE_UPLOAD init API must return both a publish_id (identifies the publish task for later status polling) and an upload_url (the endpoint chunks are POSTed to). If either is missing or falsy, the service cannot proceed with the chunked upload and throws this BadRequestException at tiktok.service.ts:316.
Source
Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts:316
}
/**
* 方式1:分片上传视频(POST方式)
* @param accessToken 访问令牌
* @param videoBuffer 视频文件缓冲区
* @param initData 初始化返回的数据,包含 publish_id 和 upload_url
* @returns 上传结果
*/
private async uploadVideoChunked(
accessToken: string,
videoBuffer: Buffer,
initData: any
): Promise<any> {
try {
const { publish_id, upload_url } = initData;
if (!publish_id || !upload_url) {
throw new BadRequestException('初始化响应缺少 publish_id 或 upload_url');
}
// 设置分片大小(每个分片5MB)
const chunkSize = 5 * 1024 * 1024;
const totalSize = videoBuffer.length;
const totalChunkCount = Math.ceil(totalSize / chunkSize);
this.logger.debug(`视频总大小: ${totalSize} 字节, 分片数: ${totalChunkCount}`);
// 选择视频内容类型
const contentType = 'video/mp4';
// 存储每个分片的上传响应
const uploadResponses = [];
// 上传每个分片
for (let i = 0; i < totalChunkCount; i++) {
const start = i * chunkSize;View on GitHub (pinned to d3aa8bea5b)
Solutions
- Log the raw initData right before the call and verify the TikTok init endpoint actually returned publish_id and upload_url at the top level of the object.
- Check whether the init response nests fields (e.g. under data.data) and unwrap it before passing to uploadVideoChunked.
- Verify this.apiBaseUrl targets the correct TikTok environment (sandbox vs production) and a supported API version; re-run initVideoUpload to get a fresh upload URL.
- Add an explicit check of the init HTTP call's status/error_code before using its payload, so failed inits are surfaced as init errors rather than missing-field errors.
Example fix
// before
const { publish_id, upload_url } = initData;
if (!publish_id || !upload_url) {
throw new BadRequestException('初始化响应缺少 publish_id 或 upload_url');
}
// after
const payload = initData?.data?.data ?? initData?.data ?? initData; // unwrap nested response
const { publish_id, upload_url } = payload ?? {};
if (!publish_id || !upload_url) {
this.logger.error('TikTok init payload:', JSON.stringify(initData));
throw new BadRequestException(`初始化响应缺少 publish_id 或 upload_url: ${JSON.stringify(initData).slice(0, 500)}`);
} Defensive patterns
Strategy: validation
Validate before calling
function canChunkUpload(initData) {
return !!initData && typeof initData.publish_id === 'string' && initData.publish_id.length > 0
&& typeof initData.upload_url === 'string' && initData.upload_url.startsWith('http');
}
if (!canChunkUpload(initData)) {
initData = await initVideoUpload(accessToken, videoBuffer.length); // re-init before uploading
} Type guard
function isInitData(v) {
return typeof v === 'object' && v !== null
&& typeof (v as { publish_id?: unknown }).publish_id === 'string'
&& typeof (v as { upload_url?: unknown }).upload_url === 'string';
} Try / catch
try {
const result = await uploadVideo(accessToken, videoBuffer, initData);
} catch (e) {
if (e.message.includes('初始化响应缺少')) {
// re-run the TikTok init call and retry once with fresh initData
} else throw e;
} Prevention
- Always validate initVideoUpload's response immediately after the init HTTP call, not downstream in the upload helper.
- Log the raw TikTok init payload so schema drift is caught early.
- Do not cache initData across retries — upload URLs are short-lived.
- Match the init API version to the upload path (chunked vs direct).
When it happens
Trigger: uploadVideo → uploadVideoChunked is invoked with an initData object whose publish_id or upload_url is undefined/null/empty string — i.e. initVideoUpload received a TikTok init response that omitted these fields, was wrapped differently (e.g. data.data vs data), or returned an error payload that was not detected before calling uploadVideoChunked.
Common situations: TikTok API version drift (init response schema changed or fields renamed), wrong apiBaseUrl/environment (sandbox vs production returns different payloads), an init call that failed but whose error body was parsed as success, or caller-supplied initData that was constructed manually or cached stale.
Related errors
- accountId和视频大小是必须的
- No subtitle entries in response
- OpenAI does not support multiple images
- InvalidWorkLink
- ResponseCode.AssetTooLarge
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/0596872f3b9c77ec.
Report an issue: GitHub.