{"record":{"id":"3d4eac39597daffd","repo":"zed-industries/zed","slug":"stream-has-ended-callback-cant-hold-the-lock","errorCode":null,"errorMessage":"Stream has ended, callback cant hold the lock","messagePattern":"Stream has ended, callback cant hold the lock","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/livekit_client/src/record.rs","lineNumber":90,"sourceCode":"            },\n            |err| log::error!(\"error capturing audio track: {:?}\", err),\n            Some(Duration::from_millis(100)),\n        )\n        .context(\"failed to build input stream\")?;\n\n    stream.play()?;\n    Ok(stream)\n}\n\nfn write_out(\n    samples: Arc<Mutex<Vec<i16>>>,\n    config: cpal::SupportedStreamConfig,\n    path: &Path,\n) -> Result<()> {\n    let samples = std::mem::take(\n        &mut *samples\n            .try_lock()\n            .expect(\"Stream has ended, callback cant hold the lock\"),\n    );\n    let samples: Vec<f32> = SampleTypeConverter::<_, f32>::new(samples.into_iter()).collect();\n    let mut samples = SamplesBuffer::new(\n        NonZero::new(config.channels()).expect(\"config channel is never zero\"),\n        NonZero::new(config.sample_rate()).expect(\"config sample_rate is never zero\"),\n        samples,\n    );\n    match rodio::wav_to_file(&mut samples, path) {\n        Ok(_) => Ok(()),\n        Err(e) => Err(anyhow::anyhow!(\"Failed to write wav file: {}\", e)),\n    }\n}\n","sourceCodeStart":72,"sourceCodeEnd":103,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/livekit_client/src/record.rs#L72-L103","documentation":"Asserts in write_out that samples.try_lock() succeeds because the capture stream must have ended before encoding is finalized. Firing means audio callbacks may still be running concurrently — the stream wasn't stopped/dropped before finish() called write_out — so taking the sample buffer would race with the callback.","triggerScenarios":"Thrown at crates/livekit_client/src/record.rs:90 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Drop the cpal Stream before calling write_out/finish to guarantee callbacks ceased","Replace try_lock().expect with handling for TryLockError if the lifecycle cannot be strictly ordered","Add an explicit stop/pause on the stream and join/sleep until the last callback completes"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}