{"record":{"id":"7e751c28ee83ef66","repo":"gitroomhq/postiz-app","slug":"failed-to-get-video-info","errorCode":null,"errorMessage":"Failed to get video info","messagePattern":"Failed to get video info","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"libraries/nestjs-libraries/src/videos/veo3/veo3.ts","lineNumber":89,"sourceCode":"        throw new Error('Video generation timed out');\n      }\n\n      console.log('waiting for video to be ready');\n      const data = await (\n        await fetch(\n          'https://api.kie.ai/api/v1/veo/record-info?taskId=' + taskId,\n          {\n            headers: {\n              'Content-Type': 'application/json',\n              Authorization: `Bearer ${process.env.KIEAI_API_KEY}`,\n            },\n            signal: AbortSignal.timeout(30000),\n          }\n        )\n      ).json();\n\n      if (data.code !== 200) {\n        throw new Error(data?.msg || `Failed to get video info`);\n      }\n\n      // successFlag: 0 = generating, 1 = success, anything else = failed\n      const successFlag = data?.data?.successFlag;\n      if (successFlag !== 0 && successFlag !== 1) {\n        throw new Error(\n          data?.data?.errorMessage ||\n            `Video generation failed (status ${successFlag})`\n        );\n      }\n\n      const videoUrl = data?.data?.response?.resultUrls || [];\n      if (videoUrl.length > 0) {\n        return videoUrl[0];\n      }\n\n      if (successFlag === 1) {\n        throw new Error('Video generation succeeded but no video URL returned');","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/videos/veo3/veo3.ts#L71-L107","documentation":"Each poll of the kie.ai record-info endpoint checks for code 200; any other code (auth failure, unknown taskId, rate limit, provider error) throws data.msg or 'Failed to get video info'. It's distinct from generation failure — it means the status query itself failed.","triggerScenarios":"GET api.kie.ai/api/v1/veo/record-info?taskId=... returning non-200: invalid API key mid-job, task expired/evicted from provider's store, rate limiting from the 10-second polling loop, or transient provider 5xx.","commonSituations":"API key rotated while a generation was in-flight; polling too aggressively hitting rate limits; provider pruning task records before completion; transient network errors surfacing as non-200 codes.","solutions":["Retry the status call after a short backoff before giving up (transient 5xx/rate limits are common)","Confirm the API key is still valid and the taskId exists (log both when throwing)","Add jitter/backoff to the 10s polling to avoid rate limits","If the record is truly gone (invalid taskId), restart the generation from scratch"],"exampleFix":"// before\nif (data.code !== 200) {\n  throw new Error(data?.msg || 'Failed to get video info');\n}\n\n// after\nif (data.code !== 200) {\n  if (data.code >= 500 || data.code === 429) { await timer(15000); continue; }\n  throw new Error(data?.msg || `Failed to get video info (code=${data.code})`);\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { await veo3.process(prompt); } catch (e) { if (/Failed to get video info/.test(String(e))) { await sleep(15000); return veo3.process(prompt); } throw e; }","preventionTips":["Add backoff/jitter to status polling","Keep the API key stable for the job duration","Treat 429/5xx status polls as retryable, not fatal"],"tags":["veo3","polling","kie-api","upstream"],"backgroundTag":"upstream-api-request-failed","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}