slint-ui/slint · error

LICENSE symlink " " is not necessary

Error message

LICENSE symlink "{}" is not necessary

What it means

Each symlink in a sub-LICENSES/ directory must correspond to a license actually used by files under that directory, as reported by the parsed SPDX/reuse data (the `licenses` list). This bail fires when a symlink's file stem is not in that list (or is empty), i.e. the link is unnecessary — but only when fix mode is off; with --fix-symlinks the link is silently removed instead.

Solutions

  1. Remove the unnecessary symlink from the sub-LICENSES/ directory, or re-run with `--fix-symlinks` to have it removed automatically
  2. If the license IS used, fix the SPDX data: add proper copyright/SPDX headers or REUSE.toml entries so reuse reports that license for the directory
  3. Check for a typo: symlink stem must exactly equal the license identifier, e.g. `BSD-3-Clause.txt`

Example fix

// before
package/LICENSES/MIT.txt -> ../../../LICENSES/MIT.txt   (no MIT-licensed files in package)
// after
rm package/LICENSES/MIT.txt
Defensive patterns

Strategy: validation

Validate before calling

let used: HashSet<String> = licenses_used_in_dir.into_iter().collect();
let linked: Vec<String> = std::fs::read_dir(dir.join("LICENSES"))?.filter_map(|e| e.ok()).filter(|e| is_symlink(&e.path())).filter_map(|e| e.path().file_stem()?.to_str().map(str::to_string)).collect();
let stale: Vec<_> = linked.iter().filter(|l| !used.contains(*l)).collect();

Try / catch

if let Err(e) = run_check() {
    if e.to_string().contains("is not necessary") { /* remove the stale symlink or add SPDX headers so the license is detected */ }
    else { return Err(e); }
}

Prevention

When it happens

Trigger: Running the check without --fix-symlinks while a sub-LICENSES/ dir contains a symlink whose stem matches no license used in that directory (file_stem not in `licenses`), e.g. after removing the only MIT-licensed file but leaving the MIT symlink behind.

Common situations: Stale license symlinks left after deleting/refactoring code; a license symlink added manually for a license not detected by reuse (missing SPDX headers/REUSE.toml entries); a typo in the symlink name.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/855b12a397963d65. Report an issue: GitHub.

Appendix: source

Thrown at xtask/src/reuse_compliance_check.rs:174

        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();

        let validated_link_target = lic_dir.join(&link_target).canonicalize().unwrap_or_default();
        if validated_link_target.as_os_str().is_empty() {
            if !fix_it {
                anyhow::bail!(

View on GitHub (pinned to bb937076de)