{"record":{"id":"fc1e522a2dd727fe","repo":"tonhowtf/omniget","slug":"escolha-a-pasta-de-destino-letterboxd","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/letterboxd.rs","lineNumber":356,"sourceCode":"/// Junta as partes numa lista só, sem perder de que parte cada linha veio.\nfn flatten(parts: Vec<(String, Vec<Entry>)>) -> (Vec<Entry>, Vec<PartCount>) {\n    let mut counts = Vec::new();\n    let mut all = Vec::new();\n    for (label, entries) in parts {\n        counts.push(PartCount {\n            part: label,\n            entries: entries.len(),\n        });\n        all.extend(entries);\n    }\n    all.sort_by(|a, b| b.date.cmp(&a.date).then(a.title.cmp(&b.title)));\n    (all, counts)\n}\n\npub async fn run(opts: &Options, p: ProgressFn) -> Result<ExportResult> {\n    let dest = PathBuf::from(opts.dest.trim());\n    if opts.dest.trim().is_empty() {\n        return Err(anyhow!(\"escolha a pasta de destino\"));\n    }\n    std::fs::create_dir_all(&dest)?;\n    let f = Fetcher::new(opts.delay_ms, opts.session_netscape.as_deref(), DOMAIN)?;\n\n    // 1. O ZIP: local ou baixado com a sessão.\n    let (bytes, source) = match opts.zip_path.as_deref().map(str::trim) {\n        Some(path) if !path.is_empty() => {\n            report(&p, TOOL_ID, \"progress\", 0, Some(3), Some(path.to_string()));\n            (\n                std::fs::read(path).with_context(|| format!(\"não consegui ler {}\", path))?,\n                path.to_string(),\n            )\n        }\n        _ => {\n            if !f.has_session() {\n                return Err(anyhow!(\n                    \"sem sessão do Letterboxd: capture os cookies de letterboxd.com na extensão, ou aponte um ZIP já baixado de letterboxd.com/settings/data/\"\n                ));","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/letterboxd.rs#L338-L374","documentation":"Thrown at the start of the Letterboxd export tool's run() when opts.dest is blank or whitespace-only. Like the Goodreads tool, a destination directory is required because the tool writes the extracted export CSVs and generated output there.","triggerScenarios":"Calling run(&opts, p) with opts.dest set to \"\" or only whitespace.","commonSituations":"Destination field not filled in the UI; config file missing dest; user pasted a path with only spaces; defaults not initialized.","solutions":["Set opts.dest to a valid directory path before calling run.","Add UI/config validation requiring a non-empty destination.","Trim and normalize the destination input before constructing Options."],"exampleFix":"// before\nlet opts = Options { dest: String::new(), .. };\nletterboxd::run(&opts, p).await?;\n// after\nlet opts = Options { dest: \"/home/user/exports/letterboxd\".into(), .. };\nletterboxd::run(&opts, p).await?;","handlingStrategy":"validation","validationCode":"if opts.dest.trim().is_empty() {\n    return Err(anyhow!(\"dest é obrigatório: informe a pasta de saída\"));\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 letterboxd::run(&opts, &p).await {\n    Err(e) if e.to_string().contains(\"pasta de destino\") => eprintln!(\"escolha a pasta de destino no formulário\"),\n    other => other?,\n}","preventionTips":["Validate the destination input in the UI before invoking the tool","Trim and normalize the path when building Options","Default the destination to a known directory (e.g. ~/exports/letterboxd)","Pre-create the directory in setup code"],"tags":["validation","argument","letterboxd"],"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"}