gleam-lang/gleam · error
Source path should be under base
Error message
Source path should be under base
What it means
hardlink_dir computes each entry's path relative to the walk base with strip_prefix(base).expect("Source path should be under base") and panics if the entry is not under the base directory. With symlink following enabled (or a symlink escaping the tree), ignore::Walk can yield entries whose canonical paths are outside base, breaking this invariant and aborting the process.
Solutions
- Remove or fix symlinks in the source directory that point outside the base tree (`find <source> -type l -ls` to list them), then retry.
- Ensure symlinks are relative and stay within the base directory before running the hardlink operation.
- In the crate, avoid following symlinks (do not enable follow_links in the WalkBuilder) or replace the expect with a map_err that returns Error::FileIo for out-of-base entries.
Example fix
// before
let relative = source_path
.strip_prefix(base)
.expect("Source path should be under base");
// after
let relative = source_path.strip_prefix(base).map_err(|_| Error::FileIo {
action: FileIoAction::Read,
kind: FileKind::File,
path: source_path.to_string(),
err: Some("entry is not under the hardlink base directory".into()),
})?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: ensure no symlink in the source tree escapes the base directory
fn symlinks_stay_within(base: &std::path::Path) -> bool {
walkdir::WalkDir::new(base).follow_links(false).into_iter()
.filter_map(Result::ok)
.filter(|e| e.file_type().is_symlink())
.all(|e| {
std::fs::read_link(e.path())
.ok()
.and_then(|l| base.join(l).canonicalize().ok())
.map(|c| c.starts_with(base))
.unwrap_or(false)
})
} Type guard
fn is_within_base(base: &std::path::Path, p: &std::path::Path) -> bool {
p.starts_with(base)
} Prevention
- Avoid symlinks that point outside the directory being hardlinked.
- Prefer relative symlinks that stay within the project tree.
- Do not enable follow_links when walking trees that may contain external symlinks.
- Audit trees with `find <source> -type l -ls` before hardlink operations.
When it happens
Trigger: Calling compiler_cli::fs::hardlink_dir(base, dest) when the source tree contains a symlink pointing outside the base directory (e.g. a symlink to an absolute path or ../somewhere), so the walked entry path does not start with base.
Common situations: Source trees with symlinks into shared dependency folders; node_modules-style links; symlinked build-output directories; copying a project that was assembled with cross-directory links.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of gleam-lang/gleam@15b07c7830 (2026-09-14).
Data as JSON: /api/errors/fd7dcbe6c11f4166.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-cli/src/fs.rs:772
kind: FileKind::Directory,
path: current.to_path_buf(),
err: Some(err.to_string()),
})?;
for entry in entries {
let entry = entry.map_err(|err| Error::FileIo {
action: FileIoAction::Read,
kind: FileKind::Directory,
path: current.to_path_buf(),
err: Some(err.to_string()),
})?;
let source_path =
Utf8PathBuf::from_path_buf(entry.path()).expect("Non-UTF8 path in hardlink_dir");
let relative = source_path
.strip_prefix(base)
.expect("Source path should be under base");
let dest_path = dest_base.join(relative);
let file_type = entry.file_type().map_err(|err| Error::FileIo {
action: FileIoAction::Read,
kind: FileKind::File,
path: source_path.clone(),
err: Some(err.to_string()),
})?;
// Skip symlinks to prevent path traversal outside the source tree
if file_type.is_symlink() {
tracing::trace!(path=?source_path, "skipping_symlink_in_hardlink_dir");
continue;
}
if file_type.is_dir() {
mkdir(&dest_path)?;
hardlink_dir_recursive(base, &source_path, dest_base)?;View on GitHub (pinned to 15b07c7830)