{"record":{"id":"9de4ca4a32a0629b","repo":"gitroomhq/postiz-app","slug":"failed-to-generate-video","errorCode":null,"errorMessage":"Failed to generate video","messagePattern":"Failed to generate video","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"libraries/nestjs-libraries/src/videos/veo3/veo3.ts","lineNumber":62,"sourceCode":"    const value = await (\n      await fetch('https://api.kie.ai/api/v1/veo/generate', {\n        headers: {\n          'Content-Type': 'application/json',\n          Authorization: `Bearer ${process.env.KIEAI_API_KEY}`,\n        },\n        method: 'POST',\n        signal: AbortSignal.timeout(30000),\n        body: JSON.stringify({\n          prompt: customParams.prompt,\n          imageUrls: customParams?.images?.map((p) => p.path) || [],\n          model: 'veo3_fast',\n          aspectRatio: output === 'horizontal' ? '16:9' : '9:16',\n        }),\n      })\n    ).json();\n\n    if (value.code !== 200 && value.code !== 201) {\n      throw new Error(value?.msg || `Failed to generate video`);\n    }\n\n    const taskId = value.data.taskId;\n    console.log('veo3 taskId', taskId);\n    let attempts = 0;\n    const maxAttempts = 180; // ~30 minutes at 10s interval\n    while (true) {\n      if (attempts++ >= maxAttempts) {\n        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',","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/videos/veo3/veo3.ts#L44-L80","documentation":"The veo3 video generation integration calls kie.ai's create-task endpoint; if the response code is neither 200 nor 201 it throws the API's msg or the generic 'Failed to generate video'. This typically reflects an upstream API error: invalid API key, quota exhaustion, bad prompt/parameters, or provider-side failure.","triggerScenarios":"POST to api.kia.ai/api/v1/veo/create-task with an invalid/expired KIE API key, exhausted credits, disallowed aspect ratio or prompt content, or a provider outage. Any non-200/201 code triggers it.","commonSituations":"Missing or expired VITE/ENV KIE_API_KEY after redeploy; free-tier quota used up; content moderation rejecting the prompt; kie.ai API changes or downtime.","solutions":["Check the thrown message — it usually contains the upstream msg (e.g. 'insufficient balance')","Verify the API key environment variable is set and valid in the backend/orchestrator environment","Check the kie.ai dashboard for quota/billing status","Retry after fixing credentials; if the provider is down, wait and retry (the task is idempotent per request)"],"exampleFix":"// before\nconst value = await (await fetch(url, {...})).json();\nif (value.code !== 200 && value.code !== 201) throw new Error(value?.msg || 'Failed to generate video');\n\n// after: include code for diagnosis\nif (value.code !== 200 && value.code !== 201) {\n  throw new Error(`Failed to generate video (code=${value.code}): ${value?.msg ?? 'unknown'}`);\n}","handlingStrategy":"retry","validationCode":"if (!process.env.KIE_API_KEY) throw new Error('KIE_API_KEY not configured'); // fail fast before calling veo3","typeGuard":"const hasVeoCredentials = (): boolean => !!process.env.KIE_API_KEY;","tryCatchPattern":"try { await veo3.process(prompt); } catch (e) { if (/Failed to generate video/.test(String(e))) { await sleep(5000); return veo3.process(prompt); } throw e; }","preventionTips":["Validate API keys at startup","Monitor provider quota/billing","Wrap generation in a Temporal activity with retries"],"tags":["veo3","video-generation","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"}