{"record":{"id":"240bf92d55e4a4f4","repo":"yikart/AiToEarn","slug":"failed-to-get-image-dimensions","errorCode":null,"errorMessage":"Failed to get image dimensions","messagePattern":"Failed to get image dimensions","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/volcengine/volcengine.utils.ts","lineNumber":98,"sourceCode":"   */\n  static async getImageDimensions(\n    imageUrl: string,\n    logger: Logger,\n  ): Promise<{ width: number, height: number }> {\n    try {\n      logger.debug('[getImageDimensions] Fetching image dimensions', { url: imageUrl })\n\n      const response = await fetch(imageUrl)\n      if (!response.ok) {\n        throw new Error(`HTTP ${response.status}`)\n      }\n\n      const arrayBuffer = await response.arrayBuffer()\n      const buffer = Buffer.from(arrayBuffer)\n      const dimensions = sizeOf(buffer)\n\n      if (!dimensions.width || !dimensions.height) {\n        throw new Error('Failed to get image dimensions')\n      }\n\n      logger.debug('[getImageDimensions] Image dimensions retrieved', {\n        width: dimensions.width,\n        height: dimensions.height,\n      })\n\n      return {\n        width: dimensions.width,\n        height: dimensions.height,\n      }\n    }\n    catch (error) {\n      const errorMessage = getErrorMessage(error)\n      logger.error('[getImageDimensions] Failed to get image dimensions', {\n        error: errorMessage,\n        url: imageUrl,\n      })","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/volcengine/volcengine.utils.ts#L80-L116","documentation":"deleteVideo requires both videoId and accountId in the request body. Missing either triggers BadRequestException('videoId和accountId是必须的'). accountId resolves the stored access token used to authorize the delete call against TikTok.","triggerScenarios":"POST the delete route with body missing videoId or accountId, or sending them under different keys (e.g. video_id) so @Body() reads undefined.","commonSituations":"Bulk-delete loops that pass only the video object without its parent account context, or snake_case/camelCase key mismatch between client and server DTOs.","solutions":["Send { \"videoId\": \"<id>\", \"accountId\": \"<id>\" } with Content-Type: application/json.","Match the exact camelCase key names expected by @Body('videoId') and @Body('accountId').","Carry accountId through from the video list model before issuing the delete."],"exampleFix":"// before\nawait api.post('/plat/tiktok/video/delete', { video_id });\n// after\nawait api.post('/plat/tiktok/video/delete', { videoId, accountId }, { headers: { 'Content-Type': 'application/json' } });","handlingStrategy":"validation","validationCode":"if (!videoId || !accountId) throw new Error('videoId和accountId是必须的');\nawait api.post('/plat/tiktok/video/delete', { videoId, accountId }, { headers: { 'Content-Type': 'application/json' } });","typeGuard":"function isDeleteBody(v): v is { videoId: string; accountId: string } {\n  return typeof (v as any)?.videoId === 'string' && (v as any).videoId.length > 0 && typeof (v as any)?.accountId === 'string' && (v as any).accountId.length > 0;\n}","tryCatchPattern":"try {\n  await api.post('/plat/tiktok/video/delete', { videoId, accountId });\n} catch (e) {\n  if (e.response?.status === 400) console.error('删除请求体缺少videoId/accountId');\n  throw e;\n}","preventionTips":["Use exact camelCase body keys matching @Body('videoId')/@Body('accountId')","Carry accountId through from list models into delete actions","Type the delete client function with required params so omission fails at compile time"],"tags":["validation","missing-parameter","request-body"],"backgroundTag":"missing-required-parameter","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}