Skip to content

Fix AI video generation hanging forever when the provider reports failure - #1809

Open
giladresisi wants to merge 3 commits into
mainfrom
fix/video-generation-hang
Open

Fix AI video generation hanging forever when the provider reports failure#1809
giladresisi wants to merge 3 commits into
mainfrom
fix/video-generation-hang

Conversation

@giladresisi

@giladresisi giladresisi commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

What kind of change does this PR introduce?

Bug fix.

Why was this change needed?

A production user approved an AI video generation in the agent chat and got: "..." spinner forever, their approval message gone after refresh, and 1 of their 30 monthly video credits burned.

Root cause: kie.ai runs content moderation asynchronously — /veo/generate returns 200 + taskId and the rejection only appears later through record-info. The veo3 poll loop's only exit condition was non-empty resultUrls: it never inspected successFlag, explicitly whitelisted top-level code: 400, had no attempt cap and no socket timeout. A failed task therefore polled forever. The never-settling promise meant useCredit's catch-based refund never ran (credit burned), the CopilotKit SSE stream never closed (eternal spinner), and Mastra never persisted the turn (that's the vanishing approval message).

Fix, keeping all provider-specific logic inside the veo3 provider:

  • veo3.ts: bounded polling matching the HeyGen provider (180 × 10s ≈ 30 min, then throw). Keep polling only on successFlag: 0; any other flag throws with the provider's errorMessage (2/3 = failed; unknown values fail fast). Success reported without a URL throws. Top-level code !== 200 throws with the provider msg (safety wording then surfaces via generationError). AbortSignal.timeout(30000) on both fetches so a stalled socket can't hang. Once the callback rejects, the existing useCredit refund works untouched.
  • generate.video.tool.ts: try/catch returning an { error } result (outputSchema fields made optional, same shape as upload.from.url.tool.ts) instead of throwing — the agent run completes, the stream closes cleanly, the turn is persisted.
  • ai.video.tsx: the create-post modal no longer swallows errors — warning toaster on non-2xx, and on fetch rejection (network drop, where the backend may still finish and save to the media library).

Verified with a local mock kie.ai: baseline repro on the old code (failed task → endless polling with the credit row leaked unrefunded) and post-fix (code:400 / successFlag:2 / deadline paths all throw promptly with the credit refunded; chat replies with the failure message and the turn survives refresh; modal shows the toaster). Real happy-path generation verified end to end: 76s, video uploaded and saved to the media library, exactly one credit consumed.

Other information:

Follow-up commit: log the kie.ai taskId when a generation starts. While debugging the production report we could not correlate our logs with kie.ai's task history because the taskId was never recorded; with it logged, a failed generation can be looked up directly via kie.ai's record-info endpoint or dashboard.

Deliberately out of scope: out-of-app notification for timed-out generations, eager persistence of the user chat message before tool execution, error boundary around the copilot stream handler.

Checklist:

  • I have read the CONTRIBUTING guide.
  • I have signed the Contributor License Agreement (CLA) (ICLA for individuals, CCLA for entities).
  • I confirm I have not used AI to submit this PR or generate code for it.
  • I checked that there were no similar issues or PRs already open for this.
  • This PR fixes just ONE issue

🤖 Generated with Claude Code

…lure

A production user approved a veo3 generation in the agent chat and got a
spinner forever, a lost chat turn, and a burned video credit. kie.ai runs
content moderation asynchronously (generate returns 200 + taskId, the
rejection only shows up later via record-info), and the poll loop's only
exit was non-empty resultUrls: it never read successFlag and explicitly
whitelisted code 400, so a failed task looped forever. The never-settling
promise meant useCredit's catch-based refund never ran, the CopilotKit SSE
stream stayed open (eternal "..."), and Mastra never persisted the turn
(approval message gone on refresh).

Changes:
- veo3.ts: bounded polling matching the HeyGen provider (180 attempts x
  10s ~= 30 min, then throw); keep polling only on successFlag 0; throw
  with the provider's errorMessage on any other flag (2/3 = failed, and
  unknown values fail fast rather than poll to the deadline); throw on
  success reported without a URL; throw on top-level code !== 200 with the
  provider msg (safety wording is then surfaced by generationError);
  AbortSignal.timeout(30000) on both fetches so a stalled socket cannot
  hang the loop. Existing refund in useCredit works untouched once the
  callback rejects.
- generate.video.tool.ts: try/catch around generateVideo returning an
  { error } result (outputSchema fields now optional, same shape as
  upload.from.url.tool.ts) instead of throwing, so the agent run completes,
  the stream closes cleanly and the turn is persisted.
- ai.video.tsx: create-post modal no longer swallows errors - warning
  toaster on non-2xx response, and on fetch rejection (network drop; the
  backend may still finish, so the message says it may appear in the media
  library).

Verified against a local mock kie.ai: baseline repro on the old code
(failed task -> 8+ polls/80s+ with the credit row leaked unrefunded, only
killing the process ends it) and post-fix (code:400, successFlag:2 and
deadline paths all throw on the first relevant poll with the credit row
deleted; chat replies with the failure and the turn survives refresh;
modal shows the toaster). Real happy-path generation verified end to end:
76s, video uploaded and saved to the media library, exactly one credit
consumed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@postiz-contribution postiz-contribution Bot added the contribution:approved Approved contributor label Jul 30, 2026
@postiz-agent

postiz-agent Bot commented Jul 30, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

giladresisi and others added 2 commits August 1, 2026 08:48
…ovider tasks

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution:approved Approved contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant