Zackriya-Solutions/meetily · critical

Failed to spawn FFmpeg process

Error message

Failed to spawn FFmpeg process

What it means

std::process::Command::spawn returns Err when the program cannot be started. The code resolved an FFmpeg path via find_ffmpeg_path() and immediately .expect()s, so any spawn failure panics the encoding path: binary missing at the resolved path (deleted/moved after discovery), exec permission denied, OS refusing exec (macOS Gatekeeper quarantine, antivirus/SELinux/AppLocker), or fork/exec resource exhaustion.

Source

Thrown at frontend/src-tauri/src/audio/encode.rs:74

            "mp4",
            output_path.to_str().unwrap(),
        ])
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped());

    // Hide console window on Windows to prevent CMD popup during recording
    #[cfg(target_os = "windows")]
    {
        use std::os::windows::process::CommandExt;
        const CREATE_NO_WINDOW: u32 = 0x08000000;
        command.creation_flags(CREATE_NO_WINDOW);
    }

    debug!("FFmpeg command: {:?}", command);

    #[allow(clippy::zombie_processes)]
    let mut ffmpeg = command.spawn().expect("Failed to spawn FFmpeg process");
    debug!("FFmpeg process spawned");
    let mut stdin = ffmpeg.stdin.take().expect("Failed to open stdin");

    stdin.write_all(data)?;

    debug!("Dropping stdin");
    drop(stdin);
    debug!("Waiting for FFmpeg process to exit");
    let output = ffmpeg.wait_with_output().unwrap();
    let status = output.status;
    let stdout = String::from_utf8_lossy(&output.stdout);
    let stderr = String::from_utf8_lossy(&output.stderr);

    debug!("FFmpeg process exited with status: {}", status);
    debug!("FFmpeg stdout: {}", stdout);
    debug!("FFmpeg stderr: {}", stderr);

    if !status.success() {

View on GitHub (pinned to 0281737d87)

Solutions

  1. Replace .expect with ? and an anyhow context ("Failed to start FFmpeg at {path}") so the recording save path returns a user-visible error
  2. Smoke-test the binary before spawning: run Command::new(&ffmpeg_path).arg("-version") and treat failure as 'FFmpeg unavailable'
  3. On macOS, strip com.apple.quarantine from bundled ffmpeg (xattr -d) or code-sign it
  4. Re-install FFmpeg (brew install ffmpeg / winget install Gyan.FFmpeg) and confirm `ffmpeg -version` in a shell

Example fix

// before
let mut ffmpeg = command.spawn().expect("Failed to spawn FFmpeg process");

// after
let mut ffmpeg = command.spawn().with_context(|| {
    format!("Failed to start FFmpeg at {:?}", ffmpeg_path)
})?;
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::PermissionsExt;
fn ffmpeg_ok(p: &std::path::Path) -> bool {
    p.is_file()
        && (cfg!(not(unix)) || std::fs::metadata(p)
            .map(|m| m.permissions().mode() & 0o111 != 0)
            .unwrap_or(false))
}

if !ffmpeg_ok(&ffmpeg_path) {
    return Err(anyhow::anyhow!("FFmpeg at {:?} is not executable", ffmpeg_path));
}

Try / catch

match command.spawn() {
    Ok(child) => child,
    Err(e) => {
        log::error!("failed to start FFmpeg: {e}");
        return Err(anyhow::anyhow!("FFmpeg start failed: {e}").into());
    }
}

Prevention

When it happens

Trigger: find_ffmpeg_path returns a stale or decoy PATH entry that no longer executes; an unsigned bundled ffmpeg blocked by com.apple.quarantine on macOS; Windows Defender or enterprise whitelisting blocking ffmpeg.exe; memory pressure making fork fail mid-recording.

Common situations: Users without a working FFmpeg install, portable app moved after path resolution, first launch of downloaded builds carrying quarantine attributes, locked-down corporate machines.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/820de29c3d2c7bae. Report an issue: GitHub.