tonhowtf/omniget · error

defina pelo menos uma senha

Error message

defina pelo menos uma senha

What it means

When adding/setting a password, password_one demands at least one of user_password or owner_password. If both strings are empty there is no secret to build an EncryptionState from, so the function bails with 'defina pelo menos uma senha'.

Solutions

  1. Set opts.user_password to require a password to open, or opts.owner_password to lock permissions only
  2. Validate in the caller/UI that at least one password field is non-empty before invoking
  3. If the goal was only to remove a password, switch mode to "remove"

Example fix

// before
let opts = PasswordOptions { mode: "add".into(), ..Default::default() };
password_one(&opts, input)?;
// after
let opts = PasswordOptions { mode: "add".into(), user_password: "s3cret".into(), ..Default::default() };
assert!(!opts.user_password.is_empty() || !opts.owner_password.is_empty());
password_one(&opts, input)?;
Defensive patterns

Strategy: validation

Validate before calling

if opts.user_password.trim().is_empty() && opts.owner_password.trim().is_empty() {
    anyhow::bail!("informe a senha do usuário ou do proprietário");
}

Try / catch

match password_one(&opts, input) {
    Ok(item) => item,
    Err(e) if e.to_string().contains("defina pelo menos uma senha") => {
        eprintln!("informe user_password ou owner_password");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling password with mode != "remove" and both opts.user_password and opts.owner_password empty strings.

Common situations: UI form submitted with blank password fields; caller defaults all PasswordOptions fields to empty strings; config file with unset password keys.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/pdf_write.rs:134

    doc.map_err(|e| anyhow!("não abri o PDF: {}", e))
}

fn password_one(opts: &PasswordOptions, input: &str) -> anyhow::Result<WriteItem> {
    let mut doc = load(input, &opts.current_password)?;
    let pages = doc.get_pages().len();
    let note;
    if opts.mode == "remove" {
        if !doc.is_encrypted() && opts.current_password.is_empty() {
            return Err(anyhow!("esse PDF não tem senha"));
        }
        // `load_mem_with_password` já devolve o documento decifrado; basta
        // apagar o dicionário de cifra para o arquivo sair aberto.
        doc.encryption_state = None;
        doc.trailer.remove(b"Encrypt");
        note = "senha removida".to_string();
    } else {
        if opts.user_password.is_empty() && opts.owner_password.is_empty() {
            return Err(anyhow!("defina pelo menos uma senha"));
        }
        let owner = if opts.owner_password.is_empty() {
            opts.user_password.as_str()
        } else {
            opts.owner_password.as_str()
        };
        // A derivação da chave usa o /ID do arquivo. PDF gerado por
        // ferramenta simples costuma não ter: sem isso a cifra falha com um
        // "decryption error" que não diz nada.
        if doc.trailer.get(b"ID").is_err() {
            use rand::RngExt;
            let mut id = [0u8; 16];
            rand::rng().fill(&mut id);
            let id = hex::encode(id).into_bytes();
            doc.trailer.set(
                "ID",
                Object::Array(vec![
                    Object::string_literal(id.clone()),

View on GitHub (pinned to 8600b91f42)