{"record":{"id":"16efa84fdd9f8396","repo":"zed-industries/zed","slug":"only-locked-after-stream-ends","errorCode":null,"errorMessage":"Only locked after stream ends","messagePattern":"Only locked after stream ends","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/livekit_client/src/record.rs","lineNumber":70,"sourceCode":"}\n\nfn start_capture(\n    device: cpal::Device,\n    config: cpal::SupportedStreamConfig,\n    samples: Arc<Mutex<Vec<i16>>>,\n) -> Result<cpal::Stream> {\n    let stream = device\n        .build_input_stream_raw(\n            &config.config(),\n            config.sample_format(),\n            move |data, _: &_| {\n                let data = crate::get_sample_data(config.sample_format(), data).log_err();\n                let Some(data) = data else {\n                    return;\n                };\n                samples\n                    .try_lock()\n                    .expect(\"Only locked after stream ends\")\n                    .extend_from_slice(&data);\n            },\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","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/livekit_client/src/record.rs#L52-L88","documentation":"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.","triggerScenarios":"Thrown at crates/livekit_client/src/record.rs:70 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the cpal Stream is dropped/stopped before write_out takes the samples lock","If lock contention is legitimately possible, use lock() or handle the TryLockError instead of panicking in the realtime callback","Document/enforce the lifecycle: capture -> stop stream -> write_out"],"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-14T05:17:10.506Z"}