slint-ui/slint · error
" " is a not a symlink!
Error message
"{}" is a not a symlink! What it means
The xtask REUSE compliance check requires every entry of a subdirectory's LICENSES folder to be a symlink pointing at the repository's top-level LICENSES files. This bail fires in validate_license_directory when a directory entry is neither a symlink nor (in fix mode) a removable regular file. It aborts the scan because non-symlink entries would defeat the license-mirroring scheme.
Solutions
- Replace the regular file in the sub-LICENSES/ directory with a relative symlink to the corresponding file in the top-level LICENSES/ directory, e.g. `ln -sf ../../../LICENSES/Apache-2.0.txt Apache-2.0.txt`
- Re-run with `cargo xtask reuse-compliance-check --fix-symlinks` so regular files are removed and correct symlinks are recreated
- Check how the repo was checked out/archived; ensure symlinks are preserved (git config core.symlinks true; avoid zip archives)
Example fix
// before package/LICENSES/Apache-2.0.txt (regular copy of the license) // after ln -sf ../../../LICENSES/Apache-2.0.txt package/LICENSES/Apache-2.0.txt
Defensive patterns
Strategy: validation
Validate before calling
let bad: Vec<_> = std::fs::read_dir("path/to/LICENSES")?.filter_map(|e| e.ok()).map(|e| e.path()).filter(|p| !is_symlink(p)).collect();
if !bad.is_empty() { eprintln!("non-symlinks: {:?}", bad); } Type guard
fn is_symlink(path: &std::path::Path) -> bool {
std::fs::symlink_metadata(path).map(|m| m.file_type().is_symlink()).unwrap_or(false)
} Try / catch
match validate_result {
Err(e) if e.to_string().contains("is a not a symlink") => {
// re-run with --fix-symlinks or fix the entry manually
}
Err(e) => return Err(e),
Ok(()) => {}
} Prevention
- Never copy license files into sub-LICENSES/ dirs; always symlink to the top-level LICENSES/ file
- Ensure git and CI archives preserve symlinks (core.symlinks=true on Windows, avoid zip artifacts)
- Run the check with --fix-symlinks after bulk refactors
When it happens
Trigger: Running `cargo xtask reuse-compliance-check` (scan_symlinks → validate_license_directory) when a LICENSES/ subdirectory contains a regular file or another directory, or a regular file exists and --fix-symlinks was not passed.
Common situations: A developer copied a real LICENSE file into a package's LICENSES/ dir instead of creating a symlink; a build step materialized symlinks into regular files (e.g. zip/tar extraction on Windows or CI without symlink support); a stray directory was created in LICENSES/.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- LICENSE symlink " " does not point to a file
- Invalid extension for LICENSE symlink
- License symlink " " does not point to any existing location
- LICENSE symlink " " is not necessary
- LICENSE symlink " " points outside the repository
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/40ae253d7bb5397a.
Report an issue: GitHub.
Appendix: source
Thrown at xtask/src/reuse_compliance_check.rs:161
let mut to_add = Vec::new();
let mut to_remove = Vec::new();
for d in lic_dir
.read_dir()
.with_context(|| format!("Failed to read \"{}\" directory", lic_dir.to_string_lossy()))?
{
let child = d
.with_context(|| {
format!("Failed to read in LICENSES directory \"{}\"", lic_dir.to_string_lossy())
})?
.path();
if !is_symlink(&child) {
if child.is_file() && fix_it {
to_remove.push(child.clone());
continue;
} else {
anyhow::bail!("\"{}\" is a not a symlink!", child.to_string_lossy());
}
}
let ext = child.extension().unwrap_or_default();
let file_stem = child.file_stem().unwrap_or_default().to_string_lossy().to_string();
if ext.is_empty() || (ext != "txt" && ext != "md" && ext != "html") {
anyhow::bail!("Invalid extension for LICENSE symlink \"{}\"", child.to_string_lossy());
}
if file_stem.is_empty() || !licenses.contains(&file_stem) {
if !fix_it {
anyhow::bail!("LICENSE symlink \"{}\" is not necessary", child.to_string_lossy());
} else {
to_remove.push(child.clone());
continue;
}
} else {View on GitHub (pinned to bb937076de)