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

  1. 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`)
  2. Re-checkout the repository with symlink support enabled (git config core.symlinks true; enable Windows developer mode)
  3. 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

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


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)