Skip to content

video_generate background task stays "running" for minutes after media ready — self-deadlock between wake (expectFinal) and completeTaskRun #95701

Description

@bigbrother666sh

Summary

video_generate background tasks stay in running status for several minutes after the generated video is ready, blocking the next segment in sequential video-production workflows. Root cause is a self-deadlock in scheduleMediaGenerationTaskCompletion: the task is only marked terminal after the completion wake returns, but the wake (expectFinal: true) awaits the requester agent's full turn, and that turn is itself blocked by the still-running task via the label-less active-task prompt guard.

Net effect on a multi-segment video job: every segment pays a ~4–5 min "release tax" on top of actual generation time, because the woken turn spins retrying the next segment until it gives up and yields — only then does the task flip to succeeded.

Reproduction

Sequential video_generate calls in one session (e.g. a crew producing clip 01, 02, 03… back-to-back, each a distinct prompt). After clip N's completion event is delivered, the agent attempts clip N+1. The runtime injects an active-task warning that suppresses the new call; the agent retries/sleeps for ~4–5 min before yielding. Clip N's task record only flips running → succeeded at that point.

Evidence

From a production run on v2026.6.8 (844f405a), state/openclaw.sqlite task_runs for one session:

task_id started_at ended_at running duration
13b0b552 12:13:51 12:18:53 5m02s
c6043e3f 12:54:07 12:59:25 5m18s
adbefdcb 15:07:02 15:07:56 0m54s

Provider is byteplus/doubao-seedance-1-0-pro-fast-251015, 4s clips — actual generation+download is ~60–90s. The remaining ~3.5–4m of each long row is the post-generation "task still running" window. The requester session trajectory shows the woken turn (12:54:35 → 12:59:23, 4m48s) reporting "stale state machine, 5 retries intercepted", and c6043e3f flips to succeeded at 12:59:25 — i.e. after the woken turn ended, not when the video was ready.

Root cause

src/agents/tools/media-generate-background-shared.ts, scheduleMediaGenerationTaskCompletion (line 382). Completion ordering:

397  executed = await withMediaGenerationTaskKeepalive({ run });   // byteplus generates video
418  recordTaskProgress({ progressSummary: "Generated media; delivering completion" });  // still running
431  const completionDelivered = await params.lifecycle.wakeTaskCompletion({ ... });     // expectFinal:true
487  params.lifecycle.completeTaskRun({ ... });                                          // ONLY HERE → succeeded

wakeTaskCompletiondeliverSubagentAnnouncementrunAnnounceAgentCall({ expectFinal: true, timeoutMs }) (src/agents/subagent-announce-delivery.ts:1454). expectFinal: true awaits the requester agent's full turn.

That woken turn, for a sequential workflow, immediately tries to start the next segment's video_generate. But the current task is still running (step at line 487 hasn't run), so resolveAttemptMediaTaskSystemPromptAddition injects:

"An active video generation background task already exists for this session. … Do not call video_generate again for the same request while that task is queued or running."

This injection is at src/agents/embedded-agent-runner/run/attempt.prompt-helpers.ts:542:

buildActiveVideoGenerationTaskPromptContextForSession(params.sessionKey),

It passes only sessionKey, no taskLabel. buildActiveMediaGenerationTaskPromptContextForSession (src/agents/media-generation-task-status-shared.ts:460) → findActiveMediaGenerationTaskForSession returns any running video task for the session regardless of prompt, so the guard suppresses every new video_generate in the session, including a clearly-different next segment.

The hard duplicate guard (createVideoGenerateDuplicateGuardResult) is label-aware and would NOT block a distinct-prompt segment — but the agent never gets there, because the label-less prompt-context warning makes it yield/retry instead.

Self-deadlock: the wake that would release the task awaits the agent turn; the agent turn can't finish because the task is still running; the task only releases when the agent gives up and yields.

Why completeTaskRun is gated behind the wake (the contract to preserve)

The current ordering exists because terminalResult is derived from completionDelivered — "a generated result without confirmed delivery is terminally unsafe for task closeout" (lines 440–452). So completeTaskRun can't simply be moved before the wake without losing that safety check.

Suggested fix

Introduce a non-blocking intermediate state between "generated" and "terminal", so the duplicate-guard / active-task prompt guard stops blocking the session as soon as the media is ready, while still deferring the final succeeded/blocked terminal outcome until delivery is confirmed:

  • After withMediaGenerationTaskKeepalive returns (video ready), mark the task e.g. delivering (or set a mediaReady/phase flag) — a state that isTaskStillBlockingDuplicateGuard and buildActiveMediaGenerationTaskPromptContextForSession treat as non-blocking for new, distinct requests.
  • Run wakeTaskCompletion (still expectFinal: true).
  • Then completeTaskRun with the terminalResult derived from completionDelivered as today.

Alternative (narrower): make buildActiveVideoGenerationTaskPromptContextForSession label-scoped or have it skip tasks whose progressSummary indicates "delivering completion", so a distinct-prompt next segment isn't suppressed. This is lower-risk but more of a string-match hack.

Environment

  • OpenClaw v2026.6.8 (commit 844f405ac1be805d5c598922a37254f12ab6d765)
  • Provider: byteplus (doubao-seedance, Volcengine ARK endpoint)
  • Runtime: Linux, gateway systemd unit, SQLite state store

Workaround in use

Instructing the crew's skill to ignore the active-task warning for distinct segments and call video_generate anyway (the hard guard already permits distinct prompts). This unblocks the workflow but leaves the task record overstaying running and allows concurrent segment generation, so it's a workaround, not a fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions