Skip to content

[Windows] Transient ffmpeg/ffprobe spawn failures (EBUSY/ETXTBSY) fail the whole render with a bare "spawn EBUSY" — no retry, no context #4058

Description

@CasbaL

Describe the bug

On Windows, spawning the managed ffmpeg/ffprobe binaries can fail transiently with EBUSY/ETXTBSY when the executable file is briefly locked — overwhelmingly antivirus real-time scanning a just-written or just-executed exe, occasionally a lingering handle from a concurrent sibling invocation (a single render shares one managed ffmpeg binary across many stages: media probing, frame extraction, audio mix, encode).

When that happens, the whole render fails with a bare, context-free error and there is no retry:

Error: spawn EBUSY

We observed this repeatedly in an Electron integration of the producer: a Delivery transcode step used the same managed ffmpeg.exe seconds before the render pipeline started; the render then failed on its first ffmpeg/ffprobe spawn and the user-facing export was lost. Re-running the export afterwards succeeded — confirming the condition is transient.

Root cause

All three spawn sites surface the raw child-process error without classification or retry:

  • packages/engine/src/utils/runFfmpeg.ts — the spawn error arrives inside the ManagedChildProcess outcome (reason: "spawn_error", raw error).
  • packages/producer/src/services/audioExtractor.ts (runFFmpeg) — ffmpeg.on("error", reject).
  • packages/producer/src/services/render/audioPadTrim.ts (runFfprobeJson) — throws outcome.error raw.

Node reports these as Error: spawn EBUSY (with .code set), so neither the user nor the logs can tell which binary, which stage, or that the condition usually clears on retry.

Expected behavior

  • A transient file-lock spawn failure should be retried a few times with a short backoff — a fresh spawn almost always succeeds once the AV scan finishes.
  • When retries are exhausted, the error should name the binary and the errno, and hint at the usual cause.

Environment

  • Windows 11 x64 (applicable to any Windows host with real-time AV scanning)
  • Producer used via an embedded runtime, ~v0.8.40
  • ffmpeg.exe/ffprobe.exe resolved via managed binary paths

Proposed fix

A shared engine helper, withTransientSpawnRetry, that:

  • classifies EBUSY, ETXTBSY, EAGAIN, EMFILE, ENFILE as transient file-lock errnos;
  • re-runs the caller's existing spawn-and-wait flow with exponential backoff (250 ms base, up to 3 attempts) and logs each retry with the binary path;
  • enriches exhausted failures with the binary path, errno, and a "transient file lock (often antivirus real-time scanning)" hint;
  • wraps the caller's flow rather than the raw spawn() call, so a healthy spawn keeps its exact synchronous timing.

A PR is on the way.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions