{"record":{"id":"12f8ea83e213bdf9","repo":"slint-ui/slint","slug":"invalid-extension-for-license-symlink","errorCode":null,"errorMessage":"Invalid extension for LICENSE symlink \"{}\"","messagePattern":"Invalid extension for LICENSE symlink \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xtask/src/reuse_compliance_check.rs","lineNumber":169,"sourceCode":"            .with_context(|| {\n                format!(\"Failed to read in LICENSES directory \\\"{}\\\"\", lic_dir.to_string_lossy())\n            })?\n            .path();\n\n        if !is_symlink(&child) {\n            if child.is_file() && fix_it {\n                to_remove.push(child.clone());\n                continue;\n            } else {\n                anyhow::bail!(\"\\\"{}\\\" is a not a symlink!\", child.to_string_lossy());\n            }\n        }\n\n        let ext = child.extension().unwrap_or_default();\n        let file_stem = child.file_stem().unwrap_or_default().to_string_lossy().to_string();\n\n        if ext.is_empty() || (ext != \"txt\" && ext != \"md\" && ext != \"html\") {\n            anyhow::bail!(\"Invalid extension for LICENSE symlink \\\"{}\\\"\", child.to_string_lossy());\n        }\n\n        if file_stem.is_empty() || !licenses.contains(&file_stem) {\n            if !fix_it {\n                anyhow::bail!(\"LICENSE symlink \\\"{}\\\" is not necessary\", child.to_string_lossy());\n            } else {\n                to_remove.push(child.clone());\n                continue;\n            }\n        } else {\n            linked_licenses.push(file_stem.clone());\n        }\n\n        let link_target = std::fs::read_link(&child).with_context(|| {\n            format!(\"Could not extract link target of \\\"{}\\\"\", child.to_string_lossy())\n        })?;\n        let link_target_file_stem = link_target.file_stem().unwrap_or_default().to_string_lossy();\n        let link_target_extension = link_target.extension().unwrap_or_default();","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/slint-ui/slint/blob/bb937076de3f7919766c1f25e2e969367cf77e9a/xtask/src/reuse_compliance_check.rs#L151-L187","documentation":"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.","triggerScenarios":"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).","commonSituations":"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/.","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"],"exampleFix":"// before\npackage/LICENSES/Apache-2.0 -> ../../../LICENSES/Apache-2.0.txt\n// after\npackage/LICENSES/Apache-2.0.txt -> ../../../LICENSES/Apache-2.0.txt","handlingStrategy":"validation","validationCode":"let ext = path.extension().and_then(|e| e.to_str()).unwrap_or_default();\nif !matches!(ext, \"txt\" | \"md\" | \"html\") { eprintln!(\"bad extension: {}\", path.display()); }","typeGuard":"fn has_valid_license_ext(path: &std::path::Path) -> bool {\n    path.extension().and_then(|e| e.to_str()).map_or(false, |e| matches!(e, \"txt\" | \"md\" | \"html\"))\n}","tryCatchPattern":"if let Err(e) = run_check() {\n    if e.to_string().contains(\"Invalid extension for LICENSE symlink\") { /* rename symlink to match target's name+ext */ }\n    else { return Err(e); }\n}","preventionTips":["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"],"tags":["reuse","symlink","licensing","naming"],"backgroundTag":"invalid-argument-format","analyzedSha":"bb937076de3f7919766c1f25e2e969367cf77e9a","analyzedAt":"2026-09-16T01:37:20.251Z","contentChangedAt":"2026-09-16T01:37:20.251Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}