{"record":{"id":"e94246bad09676f9","repo":"gleam-lang/gleam","slug":"non-utf8-path-in-hardlink-dir","errorCode":null,"errorMessage":"Non-UTF8 path in hardlink_dir","messagePattern":"Non-UTF8 path in hardlink_dir","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-cli/src/fs.rs","lineNumber":768,"sourceCode":"    dest_base: &Utf8Path,\n) -> Result<(), Error> {\n    let entries = std::fs::read_dir(current).map_err(|err| Error::FileIo {\n        action: FileIoAction::Read,\n        kind: FileKind::Directory,\n        path: current.to_path_buf(),\n        err: Some(err.to_string()),\n    })?;\n\n    for entry in entries {\n        let entry = entry.map_err(|err| Error::FileIo {\n            action: FileIoAction::Read,\n            kind: FileKind::Directory,\n            path: current.to_path_buf(),\n            err: Some(err.to_string()),\n        })?;\n\n        let source_path =\n            Utf8PathBuf::from_path_buf(entry.path()).expect(\"Non-UTF8 path in hardlink_dir\");\n\n        let relative = source_path\n            .strip_prefix(base)\n            .expect(\"Source path should be under base\");\n        let dest_path = dest_base.join(relative);\n\n        let file_type = entry.file_type().map_err(|err| Error::FileIo {\n            action: FileIoAction::Read,\n            kind: FileKind::File,\n            path: source_path.clone(),\n            err: Some(err.to_string()),\n        })?;\n\n        // Skip symlinks to prevent path traversal outside the source tree\n        if file_type.is_symlink() {\n            tracing::trace!(path=?source_path, \"skipping_symlink_in_hardlink_dir\");\n            continue;\n        }","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/gleam-lang/gleam/blob/15b07c783065c92bb016b1b74ed0995a5259850f/compiler-cli/src/fs.rs#L750-L786","documentation":"hardlink_dir recursively hard-links a directory tree; for every walked entry it converts entry.path() to Utf8PathBuf with .expect(\"Non-UTF8 path in hardlink_dir\"). Since the crate only models UTF-8 paths, a directory entry whose name contains invalid UTF-8 bytes panics with 'Non-UTF8 path in hardlink_dir'. This is an internal invariant assertion, not a recoverable error.","triggerScenarios":"Calling compiler_cli::fs::hardlink_dir(source, dest) where the source tree contains any file or subdirectory with a non-UTF-8 name.","commonSituations":"Build cache directories or dependency checkouts containing files with byte-mangled names; artifacts unpacked from archives with non-UTF-8 entry names; files created under a non-UTF-8 locale then used in a UTF-8 build environment.","solutions":["Scan the source directory for non-UTF-8 names (`find <source> -print0 | LC_ALL=C grep -zP '[\\x80-\\xFF]'`) and rename or delete them, then retry.","Regenerate the source directory contents from a trusted source so all names are UTF-8.","In the crate, replace the expect with a propagated Error::FileIo (or skip the entry) so a stray file yields a diagnostic rather than a panic mid-build."],"exampleFix":"// before\nlet source_path =\n    Utf8PathBuf::from_path_buf(entry.path()).expect(\"Non-UTF8 path in hardlink_dir\");\n\n// after\nlet source_path = Utf8PathBuf::from_path_buf(entry.path()).map_err(|p| Error::FileIo {\n    action: FileIoAction::Read,\n    kind: FileKind::File,\n    path: p.display().to_string(),\n    err: Some(\"non-UTF8 path in hardlink_dir\".into()),\n})?;","handlingStrategy":"validation","validationCode":"// Rust: verify the hardlink source tree is UTF-8-clean before calling hardlink_dir\nfn source_paths_utf8(source: &std::path::Path) -> bool {\n    walkdir::WalkDir::new(source)\n        .into_iter()\n        .filter_map(Result::ok)\n        .all(|e| e.path().to_str().is_some())\n}","typeGuard":"fn is_utf8_path(p: &std::path::Path) -> bool {\n    p.to_str().is_some()\n}","tryCatchPattern":null,"preventionTips":["Only hardlink directory trees produced by trusted UTF-8-safe tooling.","Scan the source directory for non-UTF-8 names before caching/linking operations.","Regenerate build-cache directories rather than reusing ones from other machines/locales.","Patch the crate to propagate a FileIo error instead of panicking on non-UTF-8 entries."],"tags":["filesystem","encoding","rust","panic","hardlink"],"backgroundTag":"invalid-argument-format","analyzedSha":"15b07c783065c92bb016b1b74ed0995a5259850f","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}