{"record":{"id":"e8b52d3bb9e81445","repo":"tonhowtf/omniget","slug":"escolha-a-pasta-da-biblioteca-de-destino","errorCode":null,"errorMessage":"escolha a pasta da biblioteca de destino","messagePattern":"escolha a pasta da biblioteca de destino","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/games/switch_album.rs","lineNumber":263,"sourceCode":"        ])\n        .arg(&output)\n        .output()\n        .await\n        .map_err(|e| anyhow::anyhow!(\"ffmpeg nao iniciou: {}\", e))?;\n    if !out.status.success() {\n        anyhow::bail!(\"{}\", String::from_utf8_lossy(&out.stderr).trim());\n    }\n    Ok(output)\n}\n\npub async fn run(opts: SwitchOptions, progress: ProgressFn) -> anyhow::Result<SwitchResult> {\n    let source = PathBuf::from(opts.source.trim());\n    if !source.is_dir() {\n        anyhow::bail!(\"pasta de origem não encontrada: {}\", source.display());\n    }\n    let dest_root = PathBuf::from(opts.dest.trim());\n    if opts.dest.trim().is_empty() {\n        anyhow::bail!(\"escolha a pasta da biblioteca de destino\");\n    }\n    let move_it = opts.mode == \"move\";\n\n    report(&progress, ID, \"progress\", 0, None, None);\n    let found = collect(&source, &opts.kinds);\n    let total = found.len() as u64;\n    if total == 0 {\n        report(&progress, ID, \"done\", 0, Some(0), None);\n        return Ok(SwitchResult {\n            items: Vec::new(),\n            games: Vec::new(),\n            found: 0,\n            imported: 0,\n            skipped: 0,\n            failed: 0,\n            bytes_imported: 0,\n            unknown_ids: Vec::new(),\n            dry_run: opts.dry_run,","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/games/switch_album.rs#L245-L281","documentation":"Thrown by SwitchAlbum's `run` when the destination field (`opts.dest`) is empty or whitespace-only. The tool requires an explicit target library folder so downloads from the card are never written to an unintended default location.","triggerScenarios":"Calling `run(SwitchOptions { dest: \"\", .. })` or `dest: \"   \"` — any value whose `.trim()` is empty, regardless of source validity.","commonSituations":"Frontend form submitted without picking a destination folder; state reset cleared the dest picker; programmatic use omitted the `dest` field in the options struct.","solutions":["Set `dest` to an existing library directory path in the UI/config before calling `run`","In the frontend, disable submit until the destination folder picker has a value","If invoked programmatically, pass the intended library root explicitly"],"exampleFix":"// before\nSwitchOptions { source: card_path, dest: \"\".into(), mode: \"copy\".into() }\n// after\nSwitchOptions { source: card_path, dest: library_dir.into(), mode: \"copy\".into() }","handlingStrategy":"validation","validationCode":"if dest.trim().is_empty() {\n    return Err(\"destination library folder is required\".to_string());\n}\nif !std::path::Path::new(dest.trim()).is_dir() {\n    return Err(\"destination must be an existing directory\".to_string());\n}","typeGuard":"fn has_dest(opts: &SwitchOptions) -> bool {\n    !opts.dest.trim().is_empty()\n}","tryCatchPattern":"match switch_album::run(opts, progress).await {\n    Ok(result) => handle(result),\n    Err(e) if e.to_string().contains(\"biblioteca de destino\") => open_dest_folder_picker(),\n    Err(e) => return Err(e),\n}","preventionTips":["Disable the submit button until a destination is selected","Persist the last-used library folder as a default","Trim user input and check non-empty before sending to the backend"],"tags":["validation","empty-field","rust","tauri"],"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"}