{"record":{"id":"30487e749c5034f2","repo":"yikart/AiToEarn","slug":"accountid-30487e","errorCode":null,"errorMessage":"accountId和视频大小是必须的","messagePattern":"accountId和视频大小是必须的","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.controller.ts","lineNumber":436,"sourceCode":"    }\n  })\n  async initVideoPublish(\n    @GetToken() systemToken: TokenInfo,\n    @Body('accountId') accountId: string,\n    @Body('videoSize') videoSize: number,\n    @Body() videoInfo: {\n      title?: string;\n      description?: string;\n      privacyLevel?: string;\n      disableComment?: boolean;\n      disableDuet?: boolean;\n      disableStitch?: boolean;\n      videoCoverTimestampMs?: number;\n      hashtags?: string[];\n    }\n  ) {\n    if (!accountId || !videoSize) {\n      throw new BadRequestException('accountId和视频大小是必须的');\n    }\n\n    const accessToken = await this.tikTokAuthService.getUserAccessToken(accountId);\n    return this.tikTokService.initVideoPublish(accessToken, videoSize, videoInfo);\n  }\n\n  /**\n   * 检查视频发布状态（新版API）\n   */\n  @Post('videos/publish/status')\n  @ApiOperation({ summary: '检查视频发布状态' })\n  @ApiBody({\n    schema: {\n      type: 'object',\n      properties: {\n        accountId: { type: 'string', description: 'TikTok账号ID' },\n        publishId: { type: 'string', description: '发布ID' }\n      },","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.controller.ts#L418-L454","documentation":"initVideoPublish performs TikTok's publish-init handshake, which requires the target accountId (to resolve the access token) and videoSize in bytes (TikTok's chunked upload API needs the total size up front). Either missing triggers this 400 BadRequestException.","triggerScenarios":"Calling the init-publish endpoint with an accountId but no videoSize, or neither — e.g. a file whose size could not be read, or a body constructed before the file was stat'd.","commonSituations":"Streaming uploads where the file size is unknown; forgetting to fs.stat the file before initializing; publishing flows that assume the server reads the file itself.","solutions":["Compute the video file size in bytes and include it as videoSize in the body.","Include the accountId of the connected TikTok account.","On the client, stat/read the file metadata before calling initVideoPublish."],"exampleFix":"// before\nawait api.post('/tiktok/video/publish/init', { accountId });\n// after\nconst videoSize = fs.statSync(filePath).size;\nawait api.post('/tiktok/video/publish/init', { accountId, videoSize });","handlingStrategy":"validation","validationCode":"const videoSize = typeof file === 'object' ? file.size : require('fs').statSync(videoPath).size;\nif (!accountId || !Number.isFinite(videoSize) || videoSize <= 0) {\n  throw new Error('accountId and a positive videoSize (bytes) are required');\n}","typeGuard":"function isInitPayload(p: { accountId?: string; videoSize?: number }): p is { accountId: string; videoSize: number } {\n  return typeof p.accountId === 'string' && p.accountId !== '' &&\n         typeof p.videoSize === 'number' && Number.isFinite(p.videoSize) && p.videoSize > 0;\n}","tryCatchPattern":"try {\n  await api.post('/tiktok/video/publish/init', { accountId, videoSize });\n} catch (e) {\n  if (e.response?.status === 400) {\n    console.error('initVideoPublish requires accountId and videoSize:', e.response.data?.message);\n  }\n}","preventionTips":["Always stat/read the file before initiating a chunked upload.","Reject zero-byte files early in the client pipeline.","Keep accountId in a shared upload-context object used by all publish steps."],"tags":["bad-request","validation","tiktok","upload","missing-parameter"],"backgroundTag":"missing-required-parameter","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}