tonhowtf/omniget · error

não gravei

Error message

não gravei {}: {}

What it means

This error is raised in the redaction tool's `run` when `doc.save(&output)` fails after redaction regions were applied. It wraps the underlying PDF write error with the output path and original error text via `anyhow!`, so the message literally means 'did not write <path>: <cause>'. It indicates the redacted document could not be persisted to disk.

Solutions

  1. Check the underlying error text after the colon — it names the real cause (NotFound, PermissionDenied, storage full, etc.)
  2. Verify the output directory exists and is writable before running redaction
  3. Close any program that has the output file open (viewers keep write locks on Windows)
  4. Free disk space or write to a different volume
  5. If the PDF library fails to serialize, try saving to a fresh temp path then rename into place

Example fix

// before
let out = PathBuf::from("C:/Program Files/app/output.pdf");
doc.save(&out).map_err(|e| anyhow!("não gravei {}: {}", out.display(), e))?;
// after
let out = dirs::document_dir().unwrap().join("redacted.pdf");
if let Some(parent) = out.parent() { std::fs::create_dir_all(parent)?; }
doc.save(&out).map_err(|e| anyhow!("não gravei {}: {}", out.display(), e))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust
fn ensure_writable(path: &std::path::Path) -> anyhow::Result<()> {
    let dir = path.parent().ok_or_else(|| anyhow!("sem diretório"))?;
    if !dir.exists() { std::fs::create_dir_all(dir)?; }
    let probe = dir.join(".write_probe");
    std::fs::write(&probe, b"")?;
    std::fs::remove_file(&probe)?;
    if path.exists() && std::fs::metadata(path)?.permissions().readonly() {
        anyhow::bail!("arquivo de saída é read-only");
    }
    Ok(())
}

Type guard

fn is_writable_output(path: &std::path::Path) -> bool {
    path.parent().map(|d| d.is_dir()).unwrap_or(false)
        && std::fs::OpenOptions::new().append(true).create(true)
            .open(path).is_ok()
}

Try / catch

match run(/* ... */) {
    Err(e) if e.to_string().starts_with("não gravei") => {
        eprintln!("falha ao gravar o PDF: {}. Verifique permissões e espaço em disco.", e);
    }
    Err(e) => return Err(e),
    Ok(report) => { /* success */ }
}

Prevention

When it happens

Trigger: Calling `run` (via `live_redact_deixa_o_check_limpo`) where the output path is unwritable: invalid directory, missing parent folder, permission denied, disk full, path locked by another process, or a failure inside the PDF library while serializing the modified document.

Common situations: Output directory was deleted or renamed between selection and save; running the app without write permission to the chosen folder; saving to a file still open in a PDF viewer (Windows file locking); disk quota/full disk; output path containing invalid characters for the filesystem.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/pdf_redact.rs:893

                Some(raw) => redact_page(&mut doc, page_id, raw, rs, opts.bar)?,
                None => (false, 0, "página não abriu no PDFium".to_string()),
            }
        };
        if !surgical {
            fallback.push(*no);
        }
        chars_removed += removed;
        by_page.push(PageReport {
            page: *no,
            areas: rs.len(),
            chars_removed: removed,
            mode: if surgical { "text" } else { "raster" }.into(),
            note,
        });
    }

    doc.save(&output)
        .map_err(|e| anyhow!("não gravei {}: {}", output.display(), e))?;

    // Conferência: o que ainda aparece dentro da região tem que virar pixel.
    report(progress, "progress", 2, 4, Some("conferindo".into()));
    let mut leftovers = 0usize;
    let out_s = output.to_string_lossy().to_string();
    if let Ok(after) = pdf::read_raw_chars(&out_s, None, "") {
        for page in &after {
            let Some(rs) = rects.get(&page.number) else {
                continue;
            };
            let n = page
                .chars
                .iter()
                .filter(|c| !c.ch.is_whitespace() && !c.empty_box())
                .filter(|c| {
                    let (cx, cy) = c.center();
                    any_inside(rs, cx, cy)
                })

View on GitHub (pinned to 8600b91f42)