{"record":{"id":"68f5fa510a9161a5","repo":"rustdesk/rustdesk","slug":"can-t-get-parent-directory-of-src-raw","errorCode":null,"errorMessage":"Can't get parent directory of {src_raw}","messagePattern":"Can't get parent directory of (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/platform/windows.rs","lineNumber":1471,"sourceCode":"    let mut path = get_reg_of(&subkey, \"InstallLocation\");\n    if path.is_empty() {\n        path = get_default_install_path();\n    }\n    path = path.trim_end_matches('\\\\').to_owned();\n    let start_menu = format!(\n        \"%ProgramData%\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs\\\\{}\",\n        crate::get_app_name()\n    );\n    let exe = format!(\"{}\\\\{}.exe\", path, crate::get_app_name());\n    (subkey, path, start_menu, exe)\n}\n\npub fn copy_raw_cmd(src_raw: &str, _raw: &str, _path: &str) -> ResultType<String> {\n    let main_raw = format!(\n        \"XCOPY \\\"{}\\\" \\\"{}\\\" /Y /E /H /C /I /K /R /Z\",\n        PathBuf::from(src_raw)\n            .parent()\n            .ok_or(anyhow!(\"Can't get parent directory of {src_raw}\"))?\n            .to_string_lossy()\n            .to_string(),\n        _path\n    );\n    return Ok(main_raw);\n}\n\npub fn copy_exe_cmd(src_exe: &str, exe: &str, path: &str) -> ResultType<String> {\n    let main_exe = copy_raw_cmd(src_exe, exe, path)?;\n    Ok(format!(\n        \"\n        {main_exe}\n        copy /Y \\\"{ORIGIN_PROCESS_EXE}\\\" \\\"{path}\\\\{broker_exe}\\\"\n        \",\n        ORIGIN_PROCESS_EXE = win_topmost_window::ORIGIN_PROCESS_EXE,\n        broker_exe = win_topmost_window::INJECTED_PROCESS_EXE,\n    ))\n}","sourceCodeStart":1453,"sourceCodeEnd":1489,"githubUrl":"https://github.com/rustdesk/rustdesk/blob/91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540/src/platform/windows.rs#L1453-L1489","documentation":"copy_raw_cmd() builds an XCOPY command string to copy a directory tree. It takes the parent directory of src_raw via PathBuf::parent(); if that returns None (src_raw is a drive root or a degenerate path), the anyhow! error is returned. XCOPY needs a source directory, so a path without a parent cannot be processed.","triggerScenarios":"Calling copy_raw_cmd(src_raw, ...) with a src_raw string whose PathBuf::parent() is None — a bare root like \"C:\\\\\", an empty/whitespace path, or a path with only a prefix.","commonSituations":"Passing the root of a drive as the update source directory, or passing a path that was never canonicalized/validated before building the command.","solutions":["Validate src_raw with Path::new(src_raw).parent().is_some() (and that it exists) before calling copy_raw_cmd.","Pass a subdirectory rather than a drive root as the source path.","Canonicalize the path first (std::fs::canonicalize) so UNC prefixes and relative components don't produce degenerate parents.","If a root copy is genuinely needed, rewrite the command to copy from the root directly instead of using parent()."],"exampleFix":"// before\nlet p = PathBuf::from(src_raw).parent().ok_or(anyhow!(\"...\"))?;\n// after\nlet src = std::fs::canonicalize(src_raw)?;\nlet p = src.parent().ok_or_else(|| anyhow!(\"src is a root path: {}\", src.display()))?;","handlingStrategy":"validation","validationCode":"fn src_copyable(src_raw: &str) -> bool {\n    let p = std::path::Path::new(src_raw);\n    p.is_dir() && p.parent().is_some()\n}","typeGuard":"fn copyable_parent(src_raw: &str) -> Option<std::path::PathBuf> {\n    std::path::Path::new(src_raw).parent().map(|p| p.to_path_buf())\n}","tryCatchPattern":"match copy_raw_cmd(src_raw, dst, path) {\n    Err(e) if e.to_string().contains(\"parent directory\") => {\n        log::error!(\"source path {:?} has no parent; use a subdirectory\", src_raw);\n    }\n    other => other?,\n}","preventionTips":["Never pass a drive root or empty string as the copy source","Canonicalize source paths before building command strings","Validate that the source exists and is a directory first"],"tags":["windows","filesystem","path","xcopy"],"backgroundTag":"invalid-argument-value","analyzedSha":"91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540","analyzedAt":"2026-09-10T19:53:44.083Z","contentChangedAt":"2026-09-10T19:53:44.083Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}