tonhowtf/omniget · error

nao esta gravando

Error message

nao esta gravando

What it means

State guard in screen_record stop: the SESSION mutex was empty when stop() was called — no active recording exists (never started, already stopped, or the child died) — so there is no ffmpeg session to terminate and no file to return.

Solutions

  1. Check state() (or the recording flag) before calling stop()
  2. Treat this error as a no-op in cleanup paths: ignore 'nao esta gravando' errors
  3. Ensure start/stop are paired one-to-one; do not call stop twice

Example fix

// before
stop().await?; // fails if not recording
// after
match stop().await {
    Ok(s) => println!("saved: {:?}", s),
    Err(e) if e.to_string().contains("nao esta gravando") => {}, // nothing to do
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: validation

Validate before calling

if !screen_record::state().recording {
    eprintln!("nothing to stop; skipping stop()");
}

Try / catch

match screen_record::stop().await {
    Ok(s) => println!("saved: {:?}", s),
    Err(e) if e.to_string().contains("nao esta gravando") => { /* benign no-op */ }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling stop() when start() was never called, after stop() already ran (session is take()-n, so a second stop always fails), or after a previous start failed before registering the session.

Common situations: UI firing stop on shutdown regardless of recording state; double-clicking the stop button; scripts that unconditionally call stop in cleanup after a start that errored.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/1cc283977ee71509. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/screen_record.rs:421

async fn stop_child(mut child: tokio::process::Child) {
    if let Some(mut stdin) = child.stdin.take() {
        use tokio::io::AsyncWriteExt;
        let _ = stdin.write_all(b"q\n").await;
        let _ = stdin.flush().await;
    }
    if tokio::time::timeout(std::time::Duration::from_secs(10), child.wait())
        .await
        .is_err()
    {
        let _ = child.kill().await;
    }
}

/// Para a gravação. Normal: devolve o arquivo. Replay: descarta o anel.
pub async fn stop() -> anyhow::Result<RecordState> {
    let sess = SESSION.lock().unwrap_or_else(|e| e.into_inner()).take();
    let Some(sess) = sess else {
        return Err(anyhow!("nao esta gravando"));
    };
    stop_child(sess.child).await;
    if let Some(out) = &sess.output {
        *LAST_SAVED.lock().unwrap_or_else(|e| e.into_inner()) =
            Some(out.to_string_lossy().to_string());
    }
    if let Some(r) = &sess.ring_dir {
        let _ = std::fs::remove_dir_all(r);
    }
    Ok(state())
}

/// Replay: junta os últimos segmentos num arquivo na pasta de saída, sem
/// interromper a gravação do anel.
pub async fn save_replay() -> anyhow::Result<String> {
    let (ring, opts) = {
        let s = SESSION.lock().unwrap_or_else(|e| e.into_inner());
        let Some(sess) = s.as_ref() else {

View on GitHub (pinned to 8600b91f42)