{"record":{"id":"ec4f8e569fd8f4fe","repo":"yikart/AiToEarn","slug":"invalid-subtitle-data-z-prettifyerror-result-er","errorCode":null,"errorMessage":"Invalid subtitle data: ${z.prettifyError(result.error)}","messagePattern":"Invalid subtitle data: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/video-utils.mcp.ts","lineNumber":407,"sourceCode":"                },\n              },\n              { text: prompt },\n            ],\n          }],\n          config: {\n            responseMimeType: 'application/json',\n            responseJsonSchema: z.toJSONSchema(srtNodesSchema),\n          },\n        })\n\n        const responseText = response.text\n        if (!responseText) {\n          throw new Error('No response from Gemini')\n        }\n\n        const result = z.safeParse(srtNodesSchema, JSON.parse(responseText))\n        if (!result.success) {\n          throw new Error(`Invalid subtitle data: ${z.prettifyError(result.error)}`)\n        }\n        const subtitleData = result.data.map(node => ({\n          type: 'cue',\n          data: {\n            ...node,\n            start: srtTimestampToMs(node.start),\n            end: srtTimestampToMs(node.end),\n          },\n        } as const))\n\n        const srtContent = subtitle.stringifySync(subtitleData, { format: 'SRT' })\n\n        this.logger.debug('Uploading SRT file')\n        const srtBuffer = Buffer.from(srtContent, 'utf-8')\n        const uploadResult = await this.assetsService.uploadFromBuffer(userId, srtBuffer, {\n          type: AssetType.Subtitle,\n          mimeType: 'text/plain',\n          filename: `subtitle-${Date.now()}.srt`,","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/video-utils.mcp.ts#L389-L425","documentation":"getUserVideos validates queryDto.accountId before resolving the user's TikTok access token. Missing accountId yields a 400 BadRequestException('accountId是必须的'). Unlike checkAuth, this route also requires an authenticated token (systemToken.id) but the account parameter is still mandatory.","triggerScenarios":"GET the user-videos route without ?accountId=, or with an empty accountId query value.","commonSituations":"Pagination UI resets state and drops the account selection, the account list is empty so no ID is selected, or query serialization omits empty values.","solutions":["Append ?accountId=<id> to the request.","Ensure the UI disables/disables triggering video listing until a TikTok account is selected.","Verify query serialization (e.g. axios params) isn't dropping empty/undefined values silently — select a valid account first."],"exampleFix":"// before\nconst params = { accountId: selectedAccount?.id, cursor };\nawait api.get('/plat/tiktok/videos', { params });\n// after\nif (!selectedAccount?.id) return;\nawait api.get('/plat/tiktok/videos', { params: { accountId: selectedAccount.id, cursor } });","handlingStrategy":"validation","validationCode":"if (!queryDto?.accountId) throw new Error('accountId是必须的');\nawait api.get('/plat/tiktok/videos', { params: { accountId: queryDto.accountId, cursor: queryDto.cursor } });","typeGuard":"function hasAccountIdQ(v): v is { accountId: string } {\n  return typeof v?.accountId === 'string' && v.accountId.length > 0;\n}","tryCatchPattern":"try {\n  return await api.get('/plat/tiktok/videos', { params: { accountId } });\n} catch (e) {\n  if (e.response?.status === 400) { promptAccountSelection(); return []; }\n  throw e;\n}","preventionTips":["Disable list/pagination UI until an account is selected","Prune undefined/empty values from axios params objects","Centralize TikTok API calls in a client that asserts accountId presence"],"tags":["validation","missing-parameter","query-params"],"backgroundTag":"missing-required-parameter","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}