{"record":{"id":"bc7bc1396edf3994","repo":"jdx/mise","slug":"oci-system-package-layers-with-symlinks-require-a","errorCode":null,"errorMessage":"OCI system package layers with symlinks require a unix host","messagePattern":"OCI system package layers with symlinks require a unix host","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/oci/packages.rs","lineNumber":784,"sourceCode":"    if let Some(parent) = dst.parent() {\n        file::create_dir_all(parent)?;\n    }\n    match &entry.kind {\n        FsEntryKind::Dir => {\n            file::create_dir_all(&dst)?;\n            set_mode(&dst, entry.mode)?;\n        }\n        FsEntryKind::File { .. } => {\n            file::copy(&src, &dst)?;\n            set_mode(&dst, entry.mode)?;\n        }\n        FsEntryKind::Symlink { target } => {\n            #[cfg(unix)]\n            symlink(target, &dst)?;\n            #[cfg(not(unix))]\n            {\n                let _ = target;\n                bail!(\"OCI system package layers with symlinks require a unix host\");\n            }\n        }\n        FsEntryKind::Other => {\n            warn!(\n                \"oci: skipping unsupported filesystem entry {}\",\n                src.display()\n            );\n        }\n    }\n    Ok(())\n}\n\nfn set_mode(path: &Path, mode: u32) -> Result<()> {\n    #[cfg(unix)]\n    fs::set_permissions(path, fs::Permissions::from_mode(mode))?;\n    #[cfg(not(unix))]\n    {\n        let _ = (path, mode);","sourceCodeStart":766,"sourceCodeEnd":802,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/oci/packages.rs#L766-L802","documentation":"This error is thrown when materializing an OCI image layer that contains a symbolic link on a non-Unix host (e.g. Windows). The copy path only implements symlink creation via the Unix-only `std::os::unix::fs::symlink` call, so on other platforms it aborts rather than silently producing a wrong filesystem entry.","triggerScenarios":"Calling the OCI package/system-package materialization flow (`materialize_diff` -> `copy_entry`) on a non-unix platform where a layer entry has `FsEntryKind::Symlink`.","commonSituations":"Running `mise oci` image pulls/builds that incorporate Linux system packages (apt/rpm layers full of symlinks like /usr/bin -> alternatives) on a Windows developer machine or Windows CI runner.","solutions":["Run this operation on a Linux/macOS host or in a Unix-based container (e.g. WSL2 on Windows).","Rebuild or pick an image variant whose layers contain no symlinks if you must stay on Windows.","Add Windows support by materializing symlinks as copies, hardlinks, or Windows reparse points before reaching copy_entry."],"exampleFix":"// before (non-unix host)\nbail!(\"OCI system package layers with symlinks require a unix host\");\n// after (fallback: copy the target's content instead of linking)\n#[cfg(not(unix))]\n{\n    let meta = fs::metadata(&src)?;\n    if meta.is_file() {\n        fs::copy(&src, &dst)?;\n    } else {\n        bail!(\"OCI system package layers with symlinks require a unix host\");\n    }\n}","handlingStrategy":"fallback","validationCode":"if cfg!(not(unix)) {\n    let has_symlinks = layer_contains_symlinks(&manifest); // scan entries for FsEntryKind::Symlink\n    if has_symlinks {\n        eprintln!(\"layer requires a unix host; switching to WSL/container\");\n    }\n}","typeGuard":"fn is_unix() -> bool { cfg!(unix) }","tryCatchPattern":null,"preventionTips":["Run OCI image materialization on Linux/macOS or inside WSL2/containers on Windows.","Before pulling, scan the manifest/config history for system-package layers known to contain symlinks.","Document platform requirements in CI and use Unix runners for OCI tasks."],"tags":["oci","platform","symlink","windows"],"backgroundTag":"unsupported-platform","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}