{"record":{"id":"d738fb17f0d88b95","repo":"tonhowtf/omniget","slug":"escolha-pelo-menos-dois-pdfs","errorCode":null,"errorMessage":"escolha pelo menos dois PDFs","messagePattern":"escolha pelo menos dois PDFs","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/pdf.rs","lineNumber":814,"sourceCode":"\n// ── Juntar ─────────────────────────────────────────────────────────────\n\n#[derive(Debug, Clone, Deserialize)]\npub struct MergeOptions {\n    pub inputs: Vec<String>,\n    pub output: String,\n}\n\n#[derive(Debug, Clone, Serialize)]\npub struct PdfOut {\n    pub output: String,\n    pub pages: usize,\n    pub bytes: u64,\n}\n\npub fn merge(opts: &MergeOptions, progress: &super::ProgressFn) -> anyhow::Result<PdfOut> {\n    if opts.inputs.len() < 2 {\n        return Err(anyhow!(\"escolha pelo menos dois PDFs\"));\n    }\n    let api = api()?;\n    let _g = OPS.lock().unwrap_or_else(|p| p.into_inner());\n    let dest = Document::new(api)?;\n    let total = opts.inputs.len() as u64;\n    for (i, input) in opts.inputs.iter().enumerate() {\n        report(\n            progress,\n            \"progress\",\n            i as u64,\n            Some(total),\n            Some(input.clone()),\n        );\n        let src = Document::open(api, Path::new(input), None)?;\n        let all: Vec<usize> = (1..=src.pages()).collect();\n        if !all.is_empty() {\n            dest.import(&src, &all)?;\n        }","sourceCodeStart":796,"sourceCodeEnd":832,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pdf.rs#L796-L832","documentation":"merge() requires at least two input PDFs to combine. With fewer than 2 entries in MergeOptions.inputs it throws \"escolha pelo menos dois PDFs\" (\"choose at least two PDFs\") before opening any document.","triggerScenarios":"Calling merge with an empty inputs vec, or with exactly one PDF path in MergeOptions.inputs.","commonSituations":"UI allowing the merge action with one file selected; drag-and-drop dropping only one file; a filter step silently removing invalid paths leaving 0 or 1 entries.","solutions":["Pass at least two existing PDF paths in MergeOptions.inputs.","Disable/guard the merge action in the UI until inputs.len() >= 2.","If merging a single file is intentional, skip merge and copy the file instead."],"exampleFix":"// before\nmerge(&MergeOptions { inputs: vec![a], .. }, progress)\n\n// after\nif inputs.len() >= 2 { merge(&MergeOptions { inputs, .. }, progress) } else { /* copy or error in UI */ }","handlingStrategy":"validation","validationCode":"if opts.inputs.len() < 2 {\n    return Err(\"select at least two PDFs to merge\");\n}\nif opts.inputs.iter().any(|p| !std::path::Path::new(p).is_file()) {\n    return Err(\"all inputs must be existing files\");\n}","typeGuard":null,"tryCatchPattern":"match merge(&opts, &progress) {\n    Ok(out) => println!(\"merged -> {}\", out.output),\n    Err(e) if e.to_string().contains(\"pelo menos dois\") => {\n        eprintln!(\"Need 2+ PDFs; got {}\", opts.inputs.len());\n    }\n    Err(e) => eprintln!(\"merge failed: {e}\"),\n}","preventionTips":["Disable the merge button until inputs.len() >= 2 in the UI.","Filter invalid paths before building MergeOptions and report removals.","Treat single-file 'merge' as a copy operation upstream."],"tags":["pdf","merge","argument-validation","rust"],"backgroundTag":"missing-required-argument","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}