{"record":{"id":"638b65e481a0905a","repo":"tonhowtf/omniget","slug":"escolha-a-pasta-de-destino-para-organizar","errorCode":null,"errorMessage":"escolha a pasta de destino para organizar","messagePattern":"escolha a pasta de destino para organizar","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/games/clip_organizer.rs","lineNumber":327,"sourceCode":"        dirs.extend(steam::screenshot_dirs());\n    }\n    dirs.sort();\n    dirs.dedup();\n    if dirs.is_empty() {\n        anyhow::bail!(\"escolha ao menos uma pasta de capturas\");\n    }\n\n    let apps = steam::scan_apps(&steam::steam_libraries(&opts.steam_dirs));\n    let fallback = if opts.fallback_game.trim().is_empty() {\n        \"Outros\".to_string()\n    } else {\n        opts.fallback_game.trim().to_string()\n    };\n\n    let organizing = opts.mode == \"copy\" || opts.mode == \"move\";\n    let dest_root = PathBuf::from(opts.dest.trim());\n    if organizing && opts.dest.trim().is_empty() {\n        anyhow::bail!(\"escolha a pasta de destino para organizar\");\n    }\n    let move_it = opts.mode == \"move\";\n\n    report(&progress, ID, \"progress\", 0, None, None);\n    let found = collect(&dirs);\n    let total = found.len() as u64;\n\n    // No modo análise não há índice em disco: o `seen` abaixo já acha cópia\n    // repetida dentro da rodada sem escrever nada.\n    let mut index = if opts.dedupe && organizing {\n        DedupeIndex::load(&dest_root)\n    } else {\n        DedupeIndex::disabled()\n    };\n    let mut seen: std::collections::HashSet<String> = std::collections::HashSet::new();\n\n    let mut items: Vec<ImportItem> = Vec::new();\n    let (mut imported, mut skipped, mut failed, mut bytes_total) = (0u64, 0u64, 0u64, 0u64);","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/games/clip_organizer.rs#L309-L345","documentation":"This error is thrown by clip_organizer::run when the user requested an organizing mode ('copy' or 'move') but provided an empty `dest` path. Without a destination folder the organizer has nowhere to place the reorganized clips, so it fails fast via anyhow::bail before scanning any files. The message is in Portuguese: 'choose the destination folder to organize'.","triggerScenarios":"Calling run (directly or via scan_groups_by_game_without_touching_the_files / organize_moves_into_folders_by_game_and_skips_duplicates / refuses_when_there_is_nothing_to_scan) with ClipOrganizerOptions where mode is 'copy' or 'move' and opts.dest is empty or whitespace-only (opts.dest.trim().is_empty()).","commonSituations":"A frontend or CLI builds the options struct but the user never picked a destination folder in a folder-picker dialog; dest is defaulted to \"\" and mode defaults to copy/move; dest is set to a string of spaces from a clipboard paste.","solutions":["Set opts.dest to a valid existing (or creatable) directory path before calling run","Set opts.mode to 'scan' (any value other than copy/move) if you only want scanning without organizing","Validate dest in the UI/CLI before invoking run, requiring a non-empty trimmed path"],"exampleFix":"// before\nlet opts = ClipOrganizerOptions { mode: \"move\".into(), dest: \"\".into(), .. };\nrun(opts, progress).await?;\n// after\nlet opts = ClipOrganizerOptions { mode: \"move\".into(), dest: \"/home/user/Videos/organized\".into(), .. };\nrun(opts, progress).await?;","handlingStrategy":"validation","validationCode":"if opts.mode == \"copy\" || opts.mode == \"move\" {\n    if opts.dest.trim().is_empty() {\n        return Err(anyhow::anyhow!(\"dest is required when mode is copy/move\"));\n    }\n}","typeGuard":"fn has_dest_for_organizing(opts: &ClipOrganizerOptions) -> bool {\n    let organizing = opts.mode == \"copy\" || opts.mode == \"move\";\n    !organizing || !opts.dest.trim().is_empty()\n}","tryCatchPattern":"match run(opts, progress).await {\n    Ok(result) => handle(result),\n    Err(e) if e.to_string().contains(\"pasta de destino\") => prompt_user_for_destination(),\n    Err(e) => eprintln!(\"organizer failed: {e}\"),\n}","preventionTips":["Always open a folder picker and require a selection before enabling copy/move mode","Default mode to 'scan' when no destination is chosen","Trim user-provided paths and reject whitespace-only values in the UI layer"],"tags":["rust","validation","missing-argument","tauri"],"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"}