zed-industries/zed · error

Only locked after stream ends

Error message

Only locked after stream ends

What it means

Asserts in the cpal audio capture callback that the samples Mutex is uncontended: samples.try_lock() must succeed because the only other locker (write_out) runs strictly after the stream has ended. If it fires, that ordering was violated — e.g., write_out was called while the input stream was still delivering callbacks, or the stream was not fully stopped before draining.

Source

Thrown at crates/livekit_client/src/record.rs:70

}

fn start_capture(
    device: cpal::Device,
    config: cpal::SupportedStreamConfig,
    samples: Arc<Mutex<Vec<i16>>>,
) -> Result<cpal::Stream> {
    let stream = device
        .build_input_stream_raw(
            &config.config(),
            config.sample_format(),
            move |data, _: &_| {
                let data = crate::get_sample_data(config.sample_format(), data).log_err();
                let Some(data) = data else {
                    return;
                };
                samples
                    .try_lock()
                    .expect("Only locked after stream ends")
                    .extend_from_slice(&data);
            },
            |err| log::error!("error capturing audio track: {:?}", err),
            Some(Duration::from_millis(100)),
        )
        .context("failed to build input stream")?;

    stream.play()?;
    Ok(stream)
}

fn write_out(
    samples: Arc<Mutex<Vec<i16>>>,
    config: cpal::SupportedStreamConfig,
    path: &Path,
) -> Result<()> {
    let samples = std::mem::take(
        &mut *samples

View on GitHub (pinned to f4178619ac)

Solutions

  1. Ensure the cpal Stream is dropped/stopped before write_out takes the samples lock
  2. If lock contention is legitimately possible, use lock() or handle the TryLockError instead of panicking in the realtime callback
  3. Document/enforce the lifecycle: capture -> stop stream -> write_out
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/livekit_client/src/record.rs:70 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/16efa84fdd9f8396. Report an issue: GitHub.