{"record":{"id":"bf8cc5d1d38598db","repo":"yikart/AiToEarn","slug":"no-subtitle-entries-in-response","errorCode":null,"errorMessage":"No subtitle entries in response","messagePattern":"No subtitle entries in response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/subtitle.mcp.ts","lineNumber":182,"sourceCode":"                },\n              },\n              { text: prompt },\n            ],\n          }],\n          config: {\n            responseMimeType: 'application/json',\n          },\n        })\n\n        // Step 4: 解析响应\n        const responseText = response.text\n        if (!responseText) {\n          throw new Error('No response from Gemini')\n        }\n\n        const subtitleData = JSON.parse(responseText) as { entries: SubtitleEntry[] }\n        if (!subtitleData.entries || subtitleData.entries.length === 0) {\n          throw new Error('No subtitle entries in response')\n        }\n\n        this.logger.debug({ entryCount: subtitleData.entries.length }, 'Subtitle entries parsed')\n\n        // Step 5: 生成 SRT 格式\n        const srtContent = this.generateSrtFromEntries(subtitleData.entries)\n\n        // Step 6: 上传 SRT 文件\n        this.logger.debug('Uploading SRT file')\n        const srtBuffer = Buffer.from(srtContent, 'utf-8')\n        const result = await this.assetsService.uploadFromBuffer(userId, srtBuffer, {\n          type: AssetType.Subtitle,\n          mimeType: 'text/plain',\n          filename: `subtitle-${Date.now()}.srt`,\n        })\n\n        return successResult(`Subtitle generated successfully!\n","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/mcp/subtitle.mcp.ts#L164-L200","documentation":"checkAuth validates that the accountId query parameter is present before calling tikTokAuthService.isAuthorized. If the caller omits ?accountId=, a 400 BadRequestException with 'accountId是必须的' is thrown. This is a plain required-parameter guard.","triggerScenarios":"GET /plat/tiktok/auth/check without the accountId query string, or with accountId present but an empty string.","commonSituations":"Frontend builds the URL without encoding the stored account ID, the account was never created so the ID variable is undefined, or the client calls the endpoint directly (e.g. curl/Postman) forgetting the query param.","solutions":["Add ?accountId=<value> to the request URL.","Confirm the client actually stored a TikTok account ID after OAuth completed.","Check for empty-string accountId being sent by the frontend; treat undefined/empty before calling the API."],"exampleFix":"// before\nawait axios.get('/api/plat/tiktok/auth/check');\n// after\nawait axios.get(`/api/plat/tiktok/auth/check?accountId=${encodeURIComponent(accountId)}`);","handlingStrategy":"validation","validationCode":"function canCheckAuth(accountId) { return typeof accountId === 'string' && accountId.length > 0; }\nif (!canCheckAuth(accountId)) throw new Error('accountId是必须的');","typeGuard":"function hasAccountId(v): v is string { return typeof v === 'string' && v.trim().length > 0; }","tryCatchPattern":"try {\n  const { data } = await api.get('/plat/tiktok/auth/check', { params: { accountId } });\n  return data.authorized;\n} catch (e) {\n  if (e.response?.status === 400) return false; // 视为未授权/参数缺失\n  throw e;\n}","preventionTips":["Always encodeURIComponent the accountId in query strings","Check the account was persisted after OAuth before polling auth status","Add client-side form/URL builders that skip the call when accountId is falsy"],"tags":["validation","missing-parameter","tiktok"],"backgroundTag":"missing-required-parameter","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}