{"record":{"id":"aa8e6cecf0e7c7b5","repo":"tonhowtf/omniget","slug":"escolha-a-pasta-de-sa-da","errorCode":null,"errorMessage":"escolha a pasta de saída","messagePattern":"escolha a pasta de saída","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/bilibili/danmaku/export.rs","lineNumber":295,"sourceCode":"            if !out.contains(&f) {\n                out.push(f);\n            }\n        }\n    }\n    if out.is_empty() {\n        out = vec![DanmakuFormat::Xml, DanmakuFormat::Ass, DanmakuFormat::Json];\n    }\n    out\n}\n\nfn output_dir(raw: &str) -> Result<PathBuf> {\n    let trimmed = raw.trim();\n    if !trimmed.is_empty() {\n        return Ok(PathBuf::from(trimmed));\n    }\n    dirs::download_dir()\n        .or_else(dirs::home_dir)\n        .ok_or_else(|| anyhow!(\"escolha a pasta de saída\"))\n}\n\n/// `Título - P2 Nome da parte`, já sem os caracteres que o sistema recusa.\n/// Vídeo de uma parte só não ganha sufixo.\nfn file_stem(title: &str, part: &DanmakuPart, total_parts: usize) -> String {\n    let base = sanitize_filename::sanitize(title.trim());\n    let base = if base.is_empty() {\n        \"bilibili\".to_string()\n    } else {\n        base\n    };\n    if total_parts <= 1 {\n        return base;\n    }\n    let part_name = sanitize_filename::sanitize(&part.title);\n    let tail = if part_name.is_empty() || part_name == base {\n        format!(\"P{}\", part.page)\n    } else {","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/bilibili/danmaku/export.rs#L277-L313","documentation":"`resolve_output_dir` in the bilibili danmaku exporter throws this when no explicit output folder was supplied and the OS-level fallbacks (`dirs::download_dir()` then `dirs::home_dir()`) both return None. It means the exporter cannot determine where to write the danmaku file, so it refuses to guess.","triggerScenarios":"Calling the export path with an empty or whitespace-only output directory string while the process runs in an environment where the XDG/home lookup fails (e.g. stripped HOME/XDG env vars, embedded or containerized run with no home directory, or a misconfigured system where neither ~/Downloads nor ~ can be resolved).","commonSituations":"Running the Tauri app as a systemd service or in a sandboxed CI container without HOME set; running with a deleted home directory; passing an empty string from the frontend instead of a real path; Linux systems with unusual XDG_CONFIG_HOME/XDG_DOWNLOAD_DIR setups.","solutions":["Pass an explicit, non-empty output directory from the caller instead of relying on the default.","Ensure HOME (and XDG env vars on Linux) is set for the process running the app.","On first launch, persist a user-chosen output folder in settings and always send it.","As a last resort, create a known writable directory (e.g. app data dir) and pass that as output_dir."],"exampleFix":"// before\nlet out = \"\";\nexport_danmaku(parts, &out).await?;\n// after\nlet out = std::env::var(\"HOME\").map(PathBuf::from).unwrap_or_else(|_| app_data_dir());\nexport_danmaku(parts, &out.to_string_lossy().as_ref()).await?;","handlingStrategy":"validation","validationCode":"fn valid_output_dir(p: &str) -> bool {\n    let t = p.trim();\n    !t.is_empty() && std::path::Path::new(t).is_dir()\n}","typeGuard":null,"tryCatchPattern":"match export_danmaku(input, out_dir) {\n    Err(e) if e.to_string().contains(\"pasta de saída\") => prompt_user_for_folder(),\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Always pass an explicit output directory from settings rather than relying on OS defaults.","Verify HOME/XDG env vars exist when running headless or in containers.","Persist a user-chosen folder on first run and reuse it.","Fall back to the app data directory before surfacing the error to the user."],"tags":["filesystem","configuration","rust"],"backgroundTag":"missing-env-var","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"}