{"record":{"id":"706b875104a68593","repo":"tonhowtf/omniget","slug":"escolha-a-pasta-de-destino","errorCode":null,"errorMessage":"escolha a pasta de destino","messagePattern":"escolha a pasta de destino","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/blogs/medium.rs","lineNumber":628,"sourceCode":"    let title = title.trim();\n    if title.is_empty() {\n        return md.to_string();\n    }\n    for prefix in [\"## \", \"# \", \"### \"] {\n        let head = format!(\"{}{}\", prefix, title);\n        if let Some(rest) = md.strip_prefix(&head) {\n            return rest.trim_start().to_string();\n        }\n    }\n    md.to_string()\n}\n\n// ── Execução ───────────────────────────────────────────────────────────\n\npub async fn run(opts: &Options, progress: ProgressFn) -> Result<ExportResult> {\n    let dest = opts.dest.trim();\n    if dest.is_empty() {\n        return Err(anyhow!(\"escolha a pasta de destino\"));\n    }\n    if !opts.markdown && !opts.html && !opts.json {\n        return Err(anyhow!(\"escolha ao menos um formato\"));\n    }\n    let user = normalize_user(&opts.user);\n    let root = PathBuf::from(dest);\n    std::fs::create_dir_all(&root)?;\n\n    let domains: Vec<String> = COOKIE_DOMAINS.iter().map(|d| d.to_string()).collect();\n    let fetcher = Fetcher::new(opts.delay_ms, opts.session_netscape.as_deref(), &domains)?;\n\n    let mut note: Option<String> = None;\n    let mut source = \"rss\";\n    let mut docs: Vec<PostDoc> = Vec::new();\n\n    if fetcher.has_session() {\n        match from_session(&fetcher, opts, &progress).await {\n            Ok(d) => {","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/blogs/medium.rs#L610-L646","documentation":"run() validates the export options before doing any work: if opts.dest is empty (or only whitespace), there is no output folder to write the exported Medium posts into, so it fails fast with this message. This is an up-front guard so the export never starts without a destination.","triggerScenarios":"Calling run(&opts, progress) with Options.dest set to \"\", \"   \", or never filled by the UI — the trimmed string is empty.","commonSituations":"User leaves the destination folder field blank and hits Export; a preset/profile restored with a missing dest key; calling the export programmatically without setting dest.","solutions":["Set opts.dest to a valid existing (or creatable) folder path before calling run().","Validate dest in the UI: disable the Export button and show a hint until a folder is chosen via the folder picker.","On the caller side, guard with a check: if opts.dest.trim().is_empty() { prompt for folder } before invoking run().","If dest comes from config, apply a default export directory when the field is empty."],"exampleFix":"// before\nlet opts = Options { dest: String::new(), ..Default::default() };\nrun(&opts, progress).await?; // Err: escolha a pasta de destino\n// after\nlet mut opts = Options { dest: String::new(), ..Default::default() };\nif opts.dest.trim().is_empty() {\n    opts.dest = folder_picker::pick(\"pasta de destino\")?;\n}\nrun(&opts, progress).await?;","handlingStrategy":"validation","validationCode":"fn export_ready(opts: &Options) -> bool {\n    !opts.dest.trim().is_empty() && (opts.markdown || opts.html || opts.json)\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = medium::run(&opts, progress).await {\n    if e.to_string().contains(\"escolha a pasta de destino\") {\n        prompt_for_folder();\n    } else {\n        show_error(e);\n    }\n}","preventionTips":["Require the folder picker before enabling Export.","Trim and check dest in the UI on change, not just at run().","Provide a default export directory when dest is empty.","Validate all three format flags together with dest as one pre-flight check."],"tags":["rust","medium-export","validation","missing-argument"],"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"}