{"record":{"id":"06b1abe703f759e3","repo":"yikart/AiToEarn","slug":"error-response-data-error-message-06b1ab","errorCode":null,"errorMessage":"删除视频失败: ${error.response?.data?.error?.message || error.message}","messagePattern":"删除视频失败: (.+?)","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts","lineNumber":734,"sourceCode":"    accessToken: string,\n    videoId: string\n  ): Promise<any> {\n    try {\n      const { data } = await firstValueFrom(\n        this.httpService.post(`${this.apiBaseUrl}/v2/video/delete/`, {\n          video_id: videoId\n        }, {\n          headers: {\n            'Content-Type': 'application/json',\n            'Authorization': `Bearer ${accessToken}`\n          }\n        })\n      );\n\n      return { success: true };\n    } catch (error) {\n      this.logger.error('删除TikTok视频失败:', error.response?.data || error.message);\n      throw new BadRequestException(`删除视频失败: ${error.response?.data?.error?.message || error.message}`);\n    }\n  }\n\n  /**\n   * 获取视频评论列表\n   * @param accessToken 访问令牌\n   * @param videoId 视频ID\n   * @param limit 每页结果数\n   * @param cursor 分页游标\n   * @returns 评论列表\n   */\n  async getVideoComments(\n    accessToken: string,\n    videoId: string,\n    limit = 20,\n    cursor?: string\n  ): Promise<any> {\n    try {","sourceCodeStart":716,"sourceCodeEnd":752,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts#L716-L752","documentation":"The catch-all of deleteVideo (tiktok.service.ts:732-735). The POST to /v2/video/delete/ failed (HTTP error or network error), and the Axios error is converted to BadRequestException('删除视频失败: ...') with TikTok's error.message when available. Note deleteVideo returns success:true unconditionally on any 2xx, so this only fires on actual request failures.","triggerScenarios":"POST /v2/video/delete/ returns 4xx/5xx — invalid/expired access token, app lacking video deletion scope, video_id not owned by the token's user, already-deleted video, or TikTok-side 5xx/network failure.","commonSituations":"Deleting videos of an account whose token was refreshed/revoked; using a video_id from a different TikTok user; scope not re-requested after TikTok permission changes; transient TikTok outages.","solutions":["Read the '删除TikTok视频失败:' log for error.response?.data.error (code + message + log_id).","Refresh the access token if the error is 401/190 (token invalid/expired).","Verify the video_id belongs to the authenticated TikTok user and still exists.","Confirm the app has the required video management scope for deletion.","For 5xx/network errors, retry with backoff — deletion may succeed despite the error."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"if (!accessToken) throw new Error('missing access token');\nif (!videoId) throw new Error('missing videoId');","typeGuard":"null","tryCatchPattern":"try {\n  await tiktokService.deleteVideo(token, videoId);\n} catch (e) {\n  const status = (e as any).response?.status;\n  if (status && status >= 500) {\n    await retryWithBackoff(() => tiktokService.deleteVideo(token, videoId), 3);\n  } else if (status === 401) {\n    await deleteVideoWithFreshToken(videoId);\n  } else throw e;\n}","preventionTips":["Only delete videos owned by the token's authenticated user.","Retry idempotently: re-deleting an already-deleted video is safe.","Refresh tokens before long batch-delete operations.","Check TikTok status page / back off during known 5xx incidents."],"tags":["tiktok","delete","http-client","error-wrapper"],"backgroundTag":"wrapped-upstream-error","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}