Failure is sometimes recorded too early
A child attempt can mark the database run failed before an orchestrator-level retry has had a chance to recover it. Attempt state and terminal run state need separate ownership.
AiM Tours · Product & Engineering Plan
A concrete policy and implementation roadmap for preventing avoidable failures, recovering expensive long-running renders, delivering usable videos when perfection is unavailable, and telling customers only what helps them act.
Be strict before provider spend. After provider spend, preserve assets, repair deterministically, and deliver every genuinely usable result.
This plan replaces a binary “meets every invariant or fails” posture with an explicit distinction between lifecycle success and output quality. A small timing flaw should not erase a completed, expensive render. A corrupt or materially misleading video still must not be presented as successful.
The Listing Video Failure Catalog inventories the known failure contracts. Production review and code tracing show that the remaining risk is not only missing error codes. The pipeline needs a consistent disposition policy: when to retry, when to repair, when to reuse purchased assets, when to deliver a degraded result, and when failure is the only honest outcome.
A child attempt can mark the database run failed before an orchestrator-level retry has had a chance to recover it. Attempt state and terminal run state need separate ownership.
A provider may finish an expensive job before an OOM, download failure, normalization failure, or persistence failure. Retrying safely requires a durable provider-job checkpoint or a same-run persisted asset.
Small FFmpeg or timeline differences can currently fail the render even when a playable, useful output can be repaired or delivered with a warning.
completed as the prerequisite for ready email, download, and result display. Adding a new lifecycle status without updating every consumer would create avoidable regressions.Keep the existing lifecycle contract stable. Attach a second, additive quality classification and structured warnings to completed renders.
| Lifecycle status | Quality | Meaning | Customer result |
|---|---|---|---|
| completed | standard | All required stages completed and output met the normal quality contract. | Ready email, preview, and download. |
| completed | repaired | A deterministic correction was applied and the final output passed validation. | Normal delivery; correction remains internal unless it is useful to disclose. |
| completed | degraded | The result is playable and useful, but a nonessential quality expectation was not fully met. | Deliver it. Optionally show a calm Listing-page notice and “Try again.” |
| failed | unusable | No honest, usable version of the promised product could be persisted. | Failure email with the most useful safe action. |
| cancelled | Not applicable | User cancellation or a newer render intentionally superseded this run. | No failure email. |
Warnings should be structured facts, not prose-only logs. A completed render can carry zero or more records such as:
{
"code": "AVATAR_ENDED_BEFORE_TIMELINE",
"stage": "final_assembly",
"differenceSeconds": 1.42,
"repair": "FADE_AVATAR_CONTINUE_SCENES",
"customerVisible": false
}
Every failure-producing boundary should answer the same questions in the same order.
A render is terminally failed only when retries are exhausted or inappropriate, no repair can create a usable result, and no already-created result asset can be safely delivered.
Before provider spend, favor strict validation. After spend, favor recovery and salvage. Spend does not make corrupt output acceptable, but it raises the obligation to preserve and reuse completed work.
This is the working policy. Individual error codes in the catalog should map to one of these dispositions.
| Failure class | Default response | Retry or repair boundary | Final outcome | Customer disclosure |
|---|---|---|---|---|
| Customer-fixable preflight | Stop before spend. | No retry until input/account state changes. | Failed to start | Specific cause and direct action. |
| Invalid script-plan duration or read-time | Run one constrained LLM repair before TTS/video generation. | Repair only invalid scenes; validate again. | Continue, or fail before spend. | Generic retry if repair still fails. |
| Malformed model JSON | Retry parsing/generation with schema feedback. | Small bounded attempt count; do not restart purchased media stages. | Continue, or terminal planning failure. | Generic; raw model output stays internal. |
| Provider timeout, network failure, 429, or 5xx | Retry with backoff and jitter. | Resume an existing provider job when one was created. | Continue, or fail after bounded exhaustion. | Usually generic “try again.” |
| Provider credits exhausted | Do not retry. | Wait for the customer or operator to add provider credits. | Failed | Name the provider and required action. |
| Bad provider request or unsupported model capability | Do not replay the same request. | Correct validation/configuration first. | Fail before spend where possible. | Generic unless customer configuration can fix it. |
| OOM before provider work | Retry on the configured larger machine. | Stage-local retry only. | Continue, or fail after escalation. | Generic; machine details internal. |
| OOM after provider job creation | Resume the provider job or reuse the same-run asset. | Never submit a duplicate paid job merely because the worker restarted. | Continue, or fail after recovery exhaustion. | Generic. |
| FFmpeg duration or timestamp mismatch | Apply direction-aware normalization and re-probe. | Do not blindly rerun an identical deterministic command. | repaired, degraded, or unusable. | Usually none; visible degradation may get a calm notice. |
| Upload or asset-row persistence failure | Retry persistence using the existing local/provider output. | Do not regenerate upstream media. | Continue, or fail if no durable result can be stored. | Generic. |
| Final asset exists but completion update fails | Reconcile the run to the persisted result asset. | Database repair, not media regeneration. | completed | Normal ready email after reconciliation. |
| Parent process death or stale run | Watchdog inspects child runs, assets, and heartbeat. | Resume, reconcile, or terminally fail outside the dead parent. | Recovered completion or true failure. | Email only after watchdog establishes terminal state. |
| Email delivery failure | Retry email independently. | Must not change render outcome. | Render stays completed or failed as recorded. | No duplicate emails; support can resend. |
Narration is the canonical timeline because truncating spoken content is usually the most damaging result. Duration difference alone should not be a hard-failure threshold.
| Observed condition | Preferred repair | Quality result |
|---|---|---|
| Scene track is longer than narration/Presenter timeline. | Trim to the canonical timeline and apply a short ending fade where helpful. | repaired |
| Scene track ends before narration. | Extend or freeze the final visual, with a subtle motion/fade treatment if available. | repaired or degraded |
| Presenter ends before narration. | Fade the Presenter out and allow scenes plus narration to finish. | degraded |
| Presenter continues beyond narration. | Trim verified trailing silence; otherwise extend the visual timeline without cutting speech. | repaired or degraded |
| Joined video differs from the canonical timeline because of timestamp/frame rounding. | Normalize timestamps, trim to the canonical timeline, and re-probe once. | repaired |
| Repair produces a valid but slightly awkward ending. | Deliver it with a warning record; optionally offer “Try again.” | degraded |
-shortest as the quality policy. It is a useful FFmpeg safeguard, but it can silently truncate the wrong stream. Measure inputs first, choose the repair intentionally, and validate the produced output.The script-planning prompt already expresses duration and word-count limits, but silent numeric clamping can hide a semantic mismatch: the text may still be too long for the clamped Scene. The image-to-video provider also has its own hard duration limit. The validator must operate on the raw plan and on the final provider request duration, including Transition handles.
SCRIPT_PLAN_REPAIR_FAILED so malformed transport JSON, semantic plan invalidity, and provider duration incompatibility are observable separately.Retries belong at the smallest stage that can recover without repeating unrelated work or repurchasing provider output.
| Stage | Retry strategy | Idempotency requirement |
|---|---|---|
| Script/movement planning | Bounded retry for malformed JSON and transient OpenRouter errors; one semantic repair pass. | Persist only a validated plan; no downstream provider work has started. |
| Narration | Retry transient transport/provider failures; do not retry credits, authentication, or invalid voice configuration. | Reuse a persisted narration asset; persist provider request identity when supported. |
| Scene provider generation | Resume polling/import when a provider job exists. OOM retry may escalate the machine. | Persist provider job id/output checkpoint before download and normalization; same-run asset reuse first. |
| Presenter generation | Resume the HeyGen video id rather than submitting another creation request. | Persist the video id immediately after creation; reuse stored Presenter video and metadata independently. |
| Final FFmpeg assembly | Retry OOM on a larger machine; apply deterministic repair for known media defects. | All narration, Scene, and Presenter assets are already durable and must be reused. |
| Persistence and completion | Retry the failed upload/database operation or reconcile an existing asset. | Stable storage paths, fingerprints, and asset/run linkage. |
A child task may report attempt telemetry, but it should not mark the whole render run terminally failed while its retry policy can still recover. One coordinator—or a watchdog when the coordinator dies—owns the terminal transition and failure-email enqueue.
Recovery reuse must be scoped to the same render run. A customer choosing “Generate” for a fresh version should continue to receive fresh provider generation. A worker retry within that run should reuse every successfully generated asset and provider job.
Expose information when it helps the customer resolve the problem. Keep implementation diagnostics internal.
| Outcome | Listing-page surface | Internal record | |
|---|---|---|---|
completed / standard | Normal ready email. | Preview and download. | Ordinary stage metrics. |
completed / repaired | Normal ready email. | No warning unless the repair is perceptible or actionable. | Original difference, repair action, probe result. |
completed / degraded | Ready email; do not call the render failed. | Calm notice: “Your video is ready. We made a timing adjustment near the ending. You can use this version or try again.” | Warning code, severity, affected stage, support reference. |
| Provider credits exhausted | Failure email names ElevenLabs or HeyGen and links back to the Listing. | Explain that provider credits must be added before retrying. | Normalized billing classification; raw payload private. |
| Transient/internal terminal failure | Generic saved-work assurance, Listing link, and retry/help path. | Retry action and safe support reference. | Provider HTTP status, task attempt, asset ids, stack/FFmpeg diagnostics. |
Build the disposition foundation before adding isolated retries. Otherwise retries, failure emails, and database status can disagree.
Add a quality classification and structured warning records without changing the existing completed lifecycle semantics. Define one terminal-state owner.
Validate raw LLM output, read-time, Transition handles, and provider limits. Add one constrained repair pass and make silent provider-duration caps unreachable.
Probe narration, joined scenes, Presenter, and output; apply direction-aware trim/extend/fade; re-probe; record repaired or degraded quality.
Persist OpenRouter and HeyGen job identities immediately, resume polling/import, and ensure retries never repurchase completed work.
Classify transient errors, add bounded backoff, retry FFmpeg OOM on larger machines, and remove attempt-level terminal database writes.
Detect stale runs, inspect child/provider/asset state, resume or reconcile completion, then mark true failure and enqueue notification if recovery is impossible.
Verify failure email in a controlled environment, add provider-credit guidance, show degraded-output notices, and provide a safe support reference.
Report frequency, provider spend exposure, recovery rate, duplicate-job prevention, degraded-delivery rate, and terminal failures by normalized disposition.
Unit tests alone are insufficient for process death, provider resumption, and FFmpeg timing behavior. Each high-risk policy needs a failure-injection scenario.
Higher percentage of runs with provider spend that end in a deliverable asset.
No second provider creation request when a resumable job or same-run asset exists.
Failure notifications correspond only to terminal unusable runs; degraded results remain available.
These should be calibrated from a small library of real repaired videos, not chosen solely from numeric duration thresholds.