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
- Replace symlinks in the copied directory with real files/directories (e.g. `rsync -L` or `cp -rL`) before the remote build.
- Configure cross to mount the volume the symlinks point to so the links resolve in the container.
- 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
- Dereference symlinks (rsync -rL / cp -rL) before remote builds
- Avoid copying rustup-managed toolchain dirs; let cross manage its volumes
- Mount any volume a symlink points to when nesting is required
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
- a persistent volume does not exists for
- source is pointing to a directory instead of its contents
- artifact path does not start with , skipping
- remote and docker-in-docker are unlikely to work together…
- container was running.
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)