{"record":{"id":"9e5a64b9890ab6fc","repo":"Zackriya-Solutions/meetily","slug":"cannot-resume-when-not-recording","errorCode":null,"errorMessage":"Cannot resume when not recording","messagePattern":"Cannot resume when not recording","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"frontend/src-tauri/src/audio/recording_state.rs","lineNumber":193,"sourceCode":"    }\n\n    pub fn pause_recording(&self) -> Result<()> {\n        if !self.is_recording() {\n            return Err(anyhow::anyhow!(\"Cannot pause when not recording\"));\n        }\n        if self.is_paused() {\n            return Err(anyhow::anyhow!(\"Recording is already paused\"));\n        }\n\n        self.is_paused.store(true, Ordering::SeqCst);\n        *self.pause_start.lock().unwrap() = Some(Instant::now());\n        log::info!(\"Recording paused\");\n        Ok(())\n    }\n\n    pub fn resume_recording(&self) -> Result<()> {\n        if !self.is_recording() {\n            return Err(anyhow::anyhow!(\"Cannot resume when not recording\"));\n        }\n        if !self.is_paused() {\n            return Err(anyhow::anyhow!(\"Recording is not paused\"));\n        }\n\n        // Calculate pause duration and add to total\n        if let Some(pause_start) = self.pause_start.lock().unwrap().take() {\n            let pause_duration = pause_start.elapsed();\n            *self.total_pause_duration.lock().unwrap() += pause_duration;\n            log::info!(\"Recording resumed after pause of {:.2}s\", pause_duration.as_secs_f64());\n        }\n\n        self.is_paused.store(false, Ordering::SeqCst);\n        Ok(())\n    }\n\n    pub fn is_recording(&self) -> bool {\n        self.is_recording.load(Ordering::SeqCst)","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/recording_state.rs#L175-L211","documentation":"resume_recording requires an active recording; is_recording is false. Resume is only valid from the paused state (which implies recording), so resuming after a full stop or before any start is rejected.","triggerScenarios":"Resume clicked after Stop; the session auto-stopped while paused (fatal device error, recording stopped and cleared) and the user then clicks Resume; UI desync where the paused state is shown after the session ended.","commonSituations":"Device disconnected while paused, auto-stop ran, then the user clicks Resume; frontend kept a paused badge after the backend session ended.","solutions":["Gate the Resume button on live is_recording state, not cached UI state","If recording already stopped, offer Start Recording instead of resume","Listen for recording-stopped events to clear any paused indicator"],"exampleFix":"// before\nstate.resume_recording()?;\n\n// after - tolerate benign ordering races instead of failing the command\nif !state.is_recording() {\n    log::warn!(\"Resume ignored - recording already stopped\");\n    return Ok(());\n}\nstate.resume_recording()?;","handlingStrategy":"validation","validationCode":"// Frontend: gate Resume on a live recording\nif (await invoke<boolean>('is_recording')) {\n  await invoke('resume_recording');\n} else {\n  // offer Start Recording instead\n}","typeGuard":null,"tryCatchPattern":"Match on 'Cannot resume when not recording' and switch the UI to the stopped state (offer Start Recording) rather than showing an error.","preventionTips":["Clear any 'paused' badge the moment a recording-stopped event arrives","Gate Resume on is_recording, not on a cached paused flag","Remember that auto-stop (fatal device error) can end a session while it appears paused"],"tags":["state-machine","recording","invalid-transition","pause-resume"],"backgroundTag":"invalid-state-transition","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}