slint-ui/slint · error
Invalid extension for LICENSE symlink
Error message
Invalid extension for LICENSE symlink "{}" What it means
validate_license_directory derives each LICENSES entry's extension and only allows txt, md, or html so that symlinks match the top-level LICENSES file naming convention. This bail fires when a symlink in a sub-LICENSES/ directory has a missing or disallowed extension. Unlike most checks, this one fires even in fix-it mode because the correct extension cannot be inferred safely.
Solutions
- Rename the symlink so its name and extension exactly match the top-level LICENSES file it points to (e.g. Apache-2.0.txt)
- Remove the stray symlink and run `cargo xtask reuse-compliance-check --fix-symlinks` to recreate correct ones
Example fix
// before package/LICENSES/Apache-2.0 -> ../../../LICENSES/Apache-2.0.txt // after package/LICENSES/Apache-2.0.txt -> ../../../LICENSES/Apache-2.0.txt
Defensive patterns
Strategy: validation
Validate before calling
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or_default();
if !matches!(ext, "txt" | "md" | "html") { eprintln!("bad extension: {}", path.display()); } Type guard
fn has_valid_license_ext(path: &std::path::Path) -> bool {
path.extension().and_then(|e| e.to_str()).map_or(false, |e| matches!(e, "txt" | "md" | "html"))
} Try / catch
if let Err(e) = run_check() {
if e.to_string().contains("Invalid extension for LICENSE symlink") { /* rename symlink to match target's name+ext */ }
else { return Err(e); }
} Prevention
- Name license symlinks exactly as the target file, including extension (.txt/.md/.html)
- Exclude editor backups and non-license files from LICENSES/ directories
- Lint symlink names in a pre-commit hook
When it happens
Trigger: scan_symlinks → validate_license_directory encounters a symlink whose name has no extension or one other than .txt/.md/.html (e.g. LICENSES/Apache-2.0, LICENSES/MIT.rst, LICENSES/README).
Common situations: Creating a symlink named `Apache-2.0` without the .txt suffix; using an extension like .rst or .html#frag; an editor/tool creating backup files (e.g. .orig, ~) in LICENSES/.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- LICENSE symlink " " renames the license.
- " " is a not a symlink!
- LICENSE symlink " " does not point to a file
- License symlink " " does not point to any existing location
- LICENSE symlink " " is not necessary
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/12f8ea83e213bdf9.
Report an issue: GitHub.
Appendix: source
Thrown at xtask/src/reuse_compliance_check.rs:169
.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 {
linked_licenses.push(file_stem.clone());
}
let link_target = std::fs::read_link(&child).with_context(|| {
format!("Could not extract link target of \"{}\"", child.to_string_lossy())
})?;
let link_target_file_stem = link_target.file_stem().unwrap_or_default().to_string_lossy();
let link_target_extension = link_target.extension().unwrap_or_default();View on GitHub (pinned to bb937076de)