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

  1. 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`
  2. Re-run with `cargo xtask reuse-compliance-check --fix-symlinks` so regular files are removed and correct symlinks are recreated
  3. 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

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


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)