{"record":{"id":"b37d87d35a684da9","repo":"tonhowtf/omniget","slug":"escolha-a-pasta-de-destino-merge","errorCode":null,"errorMessage":"escolha a pasta de destino","messagePattern":"escolha a pasta de destino","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/lists/merge.rs","lineNumber":511,"sourceCode":"    if !e.date.is_empty() {\n        s.push_str(&format!(\" · {}\", e.date));\n    }\n    if e.times > 1 {\n        s.push_str(&format!(\" · {}×\", e.times));\n    }\n    s.push('\\n');\n    if !e.review.is_empty() {\n        let review = e.review.replace('\\n', \" \");\n        s.push_str(&format!(\"  > {}\\n\", review.trim()));\n    }\n    s\n}\n\n// ── Execução ────────────────────────────────────────────────────────────\n\npub fn run(opts: &Options, p: &ProgressFn) -> Result<MergeResult> {\n    if opts.dest.trim().is_empty() {\n        return Err(anyhow!(\"escolha a pasta de destino\"));\n    }\n    let files = collect_files(&opts.inputs);\n    if files.is_empty() && opts.spotify.is_empty() {\n        return Err(anyhow!(\n            \"aponte os exports do Letterboxd, do Trakt ou do Goodreads (JSON ou CSV)\"\n        ));\n    }\n    let total = (files.len() + opts.spotify.len().min(1)) as u64;\n    let mut sources = Vec::new();\n    let mut all: Vec<Entry> = Vec::new();\n\n    for (i, f) in files.iter().enumerate() {\n        let name = f.to_string_lossy().to_string();\n        report(\n            p,\n            TOOL_ID,\n            \"progress\",\n            i as u64,","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/merge.rs#L493-L529","documentation":"Thrown at the start of the merge tool's synchronous run() when opts.dest is blank or whitespace-only. The merge tool writes its merged output files into the destination directory, so it requires one; the check happens before files are collected.","triggerScenarios":"Calling run(&opts, &p) with opts.dest set to \"\" or only whitespace.","commonSituations":"Merge destination field left empty in the UI; config missing the dest key; default Options constructed with dest: String::new(); whitespace-only paste.","solutions":["Set opts.dest to a valid directory path before calling run.","Validate dest non-empty in the UI/config layer before invoking the tool.","Trim the input and reject empties early with a clearer message."],"exampleFix":"// before\nlet opts = merge::Options { dest: \" \".into(), .. };\nmerge::run(&opts, &p)?;\n// after\nlet dest = \"~/merged\".trim();\nassert!(!dest.is_empty());\nlet opts = merge::Options { dest: dest.to_string(), .. };\nmerge::run(&opts, &p)?;","handlingStrategy":"validation","validationCode":"if opts.dest.trim().is_empty() {\n    return Err(anyhow!(\"dest é obrigatório: informe a pasta de saída do merge\"));\n}\nstd::fs::create_dir_all(opts.dest.trim())?;","typeGuard":"fn has_dest(opts: &Options) -> bool {\n    !opts.dest.trim().is_empty()\n}","tryCatchPattern":"match merge::run(&opts, &p) {\n    Err(e) if e.to_string().contains(\"pasta de destino\") => eprintln!(\"escolha a pasta de destino antes de mesclar\"),\n    other => other?,\n}","preventionTips":["Require dest in the merge form before submitting","Trim whitespace when building Options","Default dest to a known output directory","Pre-create the destination directory in setup"],"tags":["validation","argument","merge"],"backgroundTag":"empty-required-field","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"}