cross-rs/cross · warning

copied directory contained symlinks. if the volume the link…

Error message

copied directory contained symlinks. if the volume the link points to was not mounted, the remote build may fail

What it means

Before copying directories into a remote build volume, cross scans for symbolic links (warn_symlinks after the scan reports had_symlinks). If any symlinks were found, it warns that unless the symlink target's volume is also mounted, the remote docker build may fail because the link will dangle inside the build context.

Solutions

  1. Replace symlinks in the copied directory with real files/directories (e.g. `rsync -L` or `cp -rL`) before the remote build.
  2. Configure cross to mount the volume the symlinks point to so the links resolve in the container.
  3. For rustup-managed toolchains, use cross's own toolchain volume management (`cross-util volumes create`) rather than copying a host rustup dir.

Example fix

# before: directory contains symlinks
cross build --target aarch64-unknown-linux-gnu

# after: dereference symlinks into a clean copy
rsync -rL ~/.cargo /tmp/cargo-copy
cross build --target aarch64-unknown-linux-gnu
Defensive patterns

Strategy: validation

Validate before calling

// Scan the directory for symlinks before a remote build
use std::fs;
fn contains_symlinks(dir: &std::path::Path) -> std::io::Result<bool> {
    for e in fs::read_dir(dir)? {
        let p = e?.path();
        if fs::symlink_metadata(&p)?.file_type().is_symlink() { return Ok(true); }
        if p.is_dir() { return contains_symlinks(&p); }
    }
    Ok(false)
}

Prevention

When it happens

Trigger: Calling copy_files_nocache, copy_rust_base, or copy_rust_manifest on a directory that contains symlinked files/dirs during a remote (cluster) build.

Common situations: Cargo home directories containing symlinked toolchains (rustup uses symlinks heavily); project dirs with symlinks into node_modules or vendored dependencies; shared caches linked from elsewhere on disk.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of cross-rs/cross@8c1a8aa4b6 (2026-09-13). Data as JSON: /api/errors/90b0aac38de026d4. Report an issue: GitHub.

Appendix: source

Thrown at src/docker/remote.rs:515

                };
                if link_dst_absolute.is_dir() {
                    std::os::windows::fs::symlink_dir(link_dst, dst_path)?;
                } else {
                    // symlink_file handles everything that isn't a directory
                    std::os::windows::fs::symlink_file(link_dst, dst_path)?;
                }
            }
        } else {
            had_symlinks = true;
        }
    }

    Ok(had_symlinks)
}

fn warn_symlinks(had_symlinks: bool, msg_info: &mut MessageInfo) -> Result<()> {
    if had_symlinks {
        msg_info.warn("copied directory contained symlinks. if the volume the link points to was not mounted, the remote build may fail")
    } else {
        Ok(())
    }
}

#[derive(Debug, Deserialize)]
struct CargoCompilerArtifact {
    reason: String,
    package_id: String,
    filenames: Vec<String>,
    executable: Option<String>,
}

/// Artifacts of workspace members have `path+file://` package ids,
/// while registry and git dependencies have `registry+`/`git+` ids.
/// Only the former should be copied back to the host.
fn is_workspace_artifact(artifact: &CargoCompilerArtifact) -> bool {
    artifact.package_id.starts_with("path+file://")

View on GitHub (pinned to 8c1a8aa4b6)