{"record":{"id":"0db92e804c710b2a","repo":"sxyazi/yazi","slug":"missing-filename","errorCode":null,"errorMessage":"Missing filename","messagePattern":"Missing filename","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-fs/src/casefold/unix.rs","lineNumber":13,"sourceCode":"use std::{ffi::{OsStr, OsString}, io::{self, ErrorKind}, os::{fd::AsFd, unix::ffi::OsStrExt}, path::Path};\n\nuse rustix::fs::{AtFlags, FileType, Mode, OFlags, Stat, open, statat};\n\nuse super::Casefold;\nuse crate::scanner::Scanner;\n\nimpl Casefold {\n\tpub(super) fn final_name(path: &Path) -> io::Result<OsString> {\n\t\tlet (parent, name) = path\n\t\t\t.parent()\n\t\t\t.zip(path.file_name())\n\t\t\t.ok_or_else(|| io::Error::new(ErrorKind::InvalidInput, \"Missing filename\"))?;\n\n\t\tlet parent = if parent.as_os_str().is_empty() { Path::new(\".\") } else { parent };\n\t\tlet fd = open(parent, OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC, Mode::empty())?;\n\t\tlet meta = statat(&fd, name, AtFlags::SYMLINK_NOFOLLOW)?;\n\n\t\tif Self::case_sensitive(&fd) == Some(true) {\n\t\t\tOk(name.to_owned())\n\t\t} else if Self::is_same_mount(&fd, name) {\n\t\t\tSelf::scan_fast(name, &fd, meta)\n\t\t} else {\n\t\t\tSelf::scan_full(name, &fd, meta)\n\t\t}\n\t}\n\n\tfn scan_fast(name: &OsStr, fd: &impl AsFd, stat: Stat) -> io::Result<OsString> {\n\t\tlet mut names = vec![];\n\t\tScanner::visit(&fd, |n, ino| {\n\t\t\tlet n = OsStr::from_bytes(n.to_bytes());","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/sxyazi/yazi/blob/a541adde4e5b082719a0f21a87eb3eab071ece58/yazi-fs/src/casefold/unix.rs#L1-L31","documentation":"The Unix casefold implementation needs both the parent directory and the file name component to statat() the exact name. If the path has no parent (bare relative name) or no file_name (trailing slash / '.' / '..'), it returns 'Missing filename'.","triggerScenarios":"Calling Casefold::final_name with a path like '/', './', 'foo/', or a bare 'file' that has no parent component.","commonSituations":"Passing root or directory URLs with trailing separators into the casefold lookup; constructing paths programmatically that lost their file component.","solutions":["Ensure the path passed to final_name points to an actual file, not a directory or root","Strip trailing separators before calling","Canonicalize the path first so components are well-formed"],"exampleFix":"// before\nCasefold::final_name(Path::new(\"/\"))?\n// after\nif path.file_name().is_none() { return Err(...); }\nCasefold::final_name(path)?","handlingStrategy":"validation","validationCode":"fn has_file_component(path: &std::path::Path) -> bool {\n    path.parent().is_some() && path.file_name().is_some()\n}","typeGuard":"fn split_parent_name(path: &Path) -> Option<(&Path, &std::ffi::OsStr)> {\n    path.parent().zip(path.file_name())\n}","tryCatchPattern":"match Casefold::final_name(path) {\n    Ok(n) => n,\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => return path.as_os_str().to_owned(),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Reject root/\".\"/trailing-slash paths before lookup","Canonicalize paths to normalize components","Only call final_name on concrete file paths from listings"],"tags":["unix","filesystem","path","casefold"],"backgroundTag":"invalid-argument-value","analyzedSha":"a541adde4e5b082719a0f21a87eb3eab071ece58","analyzedAt":"2026-09-18T10:12:31.659Z","contentChangedAt":"2026-09-18T10:12:31.659Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}