slint-ui/slint · error
exists but is not a symlink
Error message
{:?} exists but is not a symlink What it means
check_licenses_dir expects each required file inside the crate's LICENSES/ directory to be a symlink pointing at the root LICENSES/ file. If a regular file (or other non-symlink) exists at that path, this error is thrown because duplicates would drift from the canonical license text.
Solutions
- Delete the regular file and recreate it as a relative symlink to the root LICENSES file (e.g. `ln -s ../../LICENSES/MIT.txt LICENSES/MIT.txt`)
- Re-checkout the repository with symlink support enabled (git config core.symlinks true; enable Windows developer mode)
- Check the symlink target matches the expected relative path, as the check also validates read_link()
Example fix
# before LICENSES/MIT.txt (regular file copy) # after rm LICENSES/MIT.txt ln -s ../../LICENSES/MIT.txt LICENSES/MIT.txt
Defensive patterns
Strategy: validation
Validate before calling
for f in ["MIT.txt", "Apache-2.0.txt"] {
let p = std::path::Path::new("my-crate/LICENSES").join(f);
let meta = std::fs::symlink_metadata(&p)?;
assert!(meta.file_type().is_symlink(), "{p:?} must be a symlink");
} Type guard
fn is_symlink_pointing_to(p: &std::path::Path, target: &std::path::Path) -> bool {
std::fs::symlink_metadata(p).map_or(false, |m| m.file_type().is_symlink())
&& std::fs::read_link(p).map_or(false, |l| l == target)
} Prevention
- Never copy license files into crate LICENSES/ dirs — always symlink
- Use symlink-preserving tools (cp -a, git clone) and enable developer mode on Windows
- Verify after archive extraction (zip/tar) that symlinks survived
- Add a script that validates LICENSES symlinks before packaging
When it happens
Trigger: Someone replaced the symlink with a regular copy of the license file (e.g. by copying the crate directory without preserving symlinks, on Windows, or via a tool that dereferences symlinks).
Common situations: Cloning/archiving crates through tools or filesystems that don't support symlinks; `cp -rL`; tar extraction without symlink preservation; Windows checkouts without developer-mode symlinks.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Encountered one or multiple errors. See above for details.
- " " is a not a symlink!
- " " is not a directory
- License ` ` of crate is not in the accepted list
- LICENSE symlink " " does not point to a file
AI-assisted analysis of slint-ui/slint@3a7e700487 (2026-09-16).
Data as JSON: /api/errors/caf61bcc2011e352.
Report an issue: GitHub.
Appendix: source
Thrown at xtask/src/license_headers_check.rs:1111
.context("Failed to create LICENSES directory")?;
} else {
return Err(anyhow!(
"Missing LICENSES directory for published crate {:?}",
crate_dir
));
}
}
// Compute relative path after directory exists so canonicalize works
let rel_prefix = diff_paths(&root_licenses, &licenses_dir);
for filename in &expected_filenames {
let symlink_path = licenses_dir.join(filename);
let expected_target = rel_prefix.join(filename);
if let Ok(meta) = std::fs::symlink_metadata(&symlink_path) {
if !meta.file_type().is_symlink() {
return Err(anyhow!("{:?} exists but is not a symlink", symlink_path));
}
let target = std::fs::read_link(&symlink_path)
.context("Cannot read LICENSE symlink target")?;
if target == expected_target {
continue;
}
if self.fix_it {
eprintln!(
"Fixing up {:?} as instructed. Symlink points to wrong target.",
symlink_path
);
std::fs::remove_file(&symlink_path)
.context("Failed to remove incorrect symlink")?;
} else {
return Err(anyhow!(
"{:?} points to {:?}, expected {:?}",
symlink_path,
target,View on GitHub (pinned to 3a7e700487)