{"record":{"id":"b166dfa0beb15438","repo":"tonhowtf/omniget","slug":"escolha-o-pdf-table","errorCode":null,"errorMessage":"escolha o PDF","messagePattern":"escolha o PDF","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/pdf_table.rs","lineNumber":255,"sourceCode":"            .unwrap_or_default()\n    } else {\n        PathBuf::from(output_dir.trim())\n    };\n    std::fs::create_dir_all(&dir)?;\n    Ok(dir)\n}\n\nfn stem(input: &str) -> String {\n    Path::new(input.trim())\n        .file_stem()\n        .map(|s| super::sanitize_name(&s.to_string_lossy()))\n        .unwrap_or_else(|| \"documento\".into())\n}\n\n/// Acha as tabelas do documento sem gravar nada.\npub fn scan(opts: &Options, progress: &super::ProgressFn) -> anyhow::Result<Vec<Table>> {\n    if opts.input.trim().is_empty() {\n        return Err(anyhow!(\"escolha o PDF\"));\n    }\n    let password = if opts.password.is_empty() {\n        None\n    } else {\n        Some(opts.password.as_str())\n    };\n    let min_gap = if opts.min_gap <= 0.0 {\n        5.0\n    } else {\n        opts.min_gap\n    };\n    let min_rows = opts.min_rows.max(2);\n    let min_cols = opts.min_cols.max(2);\n\n    let progress2 = progress.clone();\n    let pages = pdf::read_pages(\n        &opts.input,\n        password,","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pdf_table.rs#L237-L273","documentation":"Guard in pdf_table::scan: the caller passed an input PDF path that is empty or whitespace-only, so there is nothing to scan for tables. The function returns early instead of attempting to open a bogus path.","triggerScenarios":"Calling scan(&Options { input: \"\".into() | \"   \".into(), .. }, progress) — typically because the field was never filled, a form dialog was cancelled, or an empty String defaulted in.","commonSituations":"Frontend sends an empty input field; config/CLI flag for the PDF omitted; variable holding the path was overwritten with \"\"; user picked no file but the tool was invoked anyway.","solutions":["Pass a real path to an existing PDF in Options.input before calling scan","Validate/trim the input path at the call site and surface a user-facing 'select a PDF' message instead of invoking the tool","Check upstream code for where Options.input is populated (dialog result, CLI arg) — an empty string usually means the selection step was skipped"],"exampleFix":"// before\nlet opts = Options { input: picked_path.unwrap_or_default(), .. };\npdf_table::scan(&opts, &progress)?;\n// after\nlet picked = picked_path.filter(|p| !p.trim().is_empty());\nlet Some(path) = picked else { anyhow::bail!(\"escolha o PDF\"); };\nlet opts = Options { input: path, .. };","handlingStrategy":"validation","validationCode":"// Rust: validate before calling scan\nfn ensure_pdf_chosen(opts: &pdf_table::Options) -> anyhow::Result<()> {\n    if opts.input.trim().is_empty() { anyhow::bail!(\"escolha o PDF\"); }\n    let p = std::path::Path::new(opts.input.trim());\n    if !p.is_file() { anyhow::bail!(\"arquivo não existe: {}\", opts.input); }\n    Ok(())\n}","typeGuard":"fn has_input(opts: &pdf_table::Options) -> bool {\n    !opts.input.trim().is_empty()\n}","tryCatchPattern":"match pdf_table::scan(&opts, &progress) {\n    Err(e) if e.to_string() == \"escolha o PDF\" => {\n        // surface file-picker dialog / usage message to the user\n        prompt_user_for_pdf()?;\n    }\n    other => other?,\n}","preventionTips":["Validate Options.input (non-empty, file exists) right after collecting it from UI/CLI/config","Never unwrap_or_default() a file-picker result into the input field","Require an explicit input flag in CLI wrappers so omission fails fast with usage help","Trim user-supplied paths before storing them in Options"],"tags":["rust","validation","missing-argument","pdf"],"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"}