{"record":{"id":"3fb0abd41d7958f0","repo":"unicity-aos/aos-ce","slug":"bundled-product-runtime-path-must-have-a-parent","errorCode":null,"errorMessage":"bundled product runtime path must have a parent","messagePattern":"bundled product runtime path must have a parent","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/unicity-aos-bootstrap/src/migration.rs","lineNumber":542,"sourceCode":"            let _ = fs::read(&pid)?;\n        }\n        Err(error) if error.kind() == io::ErrorKind::NotFound => {}\n        Err(error) => return Err(error),\n    }\n    Ok(())\n}\n\nfn checked_target_path(path: &Path) -> io::Result<PathBuf> {\n    match fs::symlink_metadata(path) {\n        Ok(metadata) => {\n            if metadata.file_type().is_symlink() || !metadata.is_dir() {\n                return invalid(\"bundled product runtime must be a real directory\");\n            }\n            path.canonicalize()\n        }\n        Err(error) if error.kind() == io::ErrorKind::NotFound => {\n            let parent = path.parent().ok_or_else(|| {\n                io::Error::new(\n                    io::ErrorKind::InvalidInput,\n                    \"bundled product runtime path must have a parent\",\n                )\n            })?;\n            let name = path.file_name().ok_or_else(|| {\n                io::Error::new(\n                    io::ErrorKind::InvalidInput,\n                    \"bundled product runtime path must have a final component\",\n                )\n            })?;\n            Ok(parent.canonicalize()?.join(name))\n        }\n        Err(error) => Err(error),\n    }\n}\n\npub(crate) fn imported_legacy_distros(home: &AosHome) -> io::Result<Vec<LegacyDistro>> {\n    let receipt = read_receipt(&home.migration_receipt())?;","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/unicity-aos-bootstrap/src/migration.rs#L524-L560","documentation":"In checked_target_path, when the bundled product runtime target path does not exist (NotFound), the code canonicalizes the parent and rejoins the final component. If the path has no parent (e.g. a bare root-relative component like Path::new(\"runtime\")), parent() returns None and this InvalidInput error is thrown. It guards the NotFound repair path from operating on degenerate paths.","triggerScenarios":"Calling migrate_runtime with a bundled product runtime target path that has no parent directory component, such as a relative single-component path or a bare root path.","commonSituations":"Passing a target like \"runtime\" or \"/\" instead of a fully qualified installation path; constructing the target programmatically with a missing base directory.","solutions":["Pass an absolute target path that includes a real parent directory (e.g. /opt/product/runtime)","Check target.parent().is_some() and target.file_name().is_some() before invoking migrate_runtime","If composing the path, join the final runtime directory onto an existing base directory"],"exampleFix":"// before\nlet target = Path::new(\"runtime\");\nmigrate_runtime(target, ...)?;\n\n// after\nlet target = Path::new(\"/opt/product/runtime\");\nmigrate_runtime(target, ...)?;","handlingStrategy":"validation","validationCode":"fn target_path_ok(target: &std::path::Path) -> bool {\n    target.parent().is_some() && target.file_name().is_some()\n}","typeGuard":"fn has_parent_and_name(p: &std::path::Path) -> Option<(std::path::PathBuf, std::ffi::OsString)> {\n    Some((p.parent()?.to_path_buf(), p.file_name()?.to_os_string()))\n}","tryCatchPattern":"match migrate_runtime(&target, ...) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"must have a parent\") =>\n        eprintln!(\"use an absolute target path with a real parent directory\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Always pass fully qualified absolute paths as migration targets","Reject single-component or root paths in your CLI/config layer","Join the runtime directory name onto an existing base directory when composing targets"],"tags":["rust","path","migration"],"backgroundTag":"invalid-argument-value","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}