jdx/mise · error
copy_link must be a relative path within the source: {}
Error message
copy_link must be a relative path within the source: {} What it means
validate_copy_link_path checks that the copy_link — a symlink to replicate in the staged remote source — is a strictly relative path inside the source. If the path contains ParentDir (..), RootDir (/) or a Windows Prefix component, mise rejects it because such links could escape the staged project boundary.
Source
Thrown at src/system/remote.rs:841
fn validate_copy_link(source: &Path, link: &Path) -> Result<()> {
validate_copy_link_path(source, link)?;
let path = source.join(link);
fs::metadata(&path)
.wrap_err_with(|| format!("copy_link target does not exist: {}", link.display()))?;
Ok(())
}
fn validate_copy_link_path(source: &Path, link: &Path) -> Result<()> {
if link.as_os_str().is_empty()
|| link.is_absolute()
|| link.components().any(|component| {
matches!(
component,
Component::ParentDir | Component::RootDir | Component::Prefix(_)
)
})
{
bail!(
"copy_link must be a relative path within the source: {}",
link.display()
);
}
let mut parent = source.to_path_buf();
for component in link.parent().unwrap_or_else(|| Path::new("")).components() {
if let Component::Normal(component) = component {
parent.push(component);
let metadata = fs::symlink_metadata(&parent).wrap_err_with(|| {
format!("copy_link parent does not exist: {}", parent.display())
})?;
if metadata.file_type().is_symlink() {
bail!(
"copy_link cannot be nested below a symbolic link: {}",
link.display()
);
}
}View on GitHub (pinned to afd2eddd3a)
Solutions
- Change copy_link to a path relative to the source root without .. or leading /
- If the target lives outside the source, stage or vendor it into the project instead
- Verify the config value with a quick path sanity check before deploying
Example fix
// before copy_link = "../../usr/bin/tool" // after copy_link = "bin/tool"
Defensive patterns
Strategy: validation
Validate before calling
function isSafeRelativeCopyLink(p) {
const c = path.posix.parse(p);
return !path.posix.isAbsolute(p) && !p.split('/').includes('..') && p !== '';
} Type guard
const isValidCopyLink = (p) => typeof p === 'string' && !path.isAbsolute(p) && !p.split('/').some(s => s === '..' || s === ''); Prevention
- Store copy_link values relative to the source root only
- Lint configs for leading '/' and '..' segments
- Vendor external targets into the project instead of linking out
When it happens
Trigger: Calling the remote staging path with a copy_link configured as an absolute path, a path starting with ../, or otherwise containing path components that traverse outside the source directory.
Common situations: Config mistakes where a user points copy_link at a shared toolchain outside the project (e.g. /usr/local/bin/x or ../../bin/x); also symlink configs copied from machines with different layouts.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- copy_link cannot be nested below a symbolic link: {}
- copy_link is not a symbolic link: {}
- remote mise path does not name an executable: {command:?}
- relative remote mise path escapes the staged project: {comma
- relative remote mise path does not name an executable: {comm
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/7b44af5429c11e96.
Report an issue: GitHub.