{"record":{"id":"4cf1bee3f81bc6e5","repo":"tikv/tikv","slug":"the-file-name-it-is-should-not-be-empty","errorCode":null,"errorMessage":"the file name (it is {}) should not be empty","messagePattern":"the file name \\(it is (.+?)\\) should not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"components/external_storage/src/local.rs","lineNumber":106,"sourceCode":"\n    async fn write(\n        &self,\n        name: &str,\n        reader: UnpinReader<'_>,\n        _content_length: u64,\n    ) -> io::Result<()> {\n        let p = Path::new(name);\n        if p.is_absolute() {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                format!(\n                    \"the file name (it is {}) should never be absolute path\",\n                    p.display()\n                ),\n            ));\n        }\n        if name.is_empty() || p.file_name().map(|s| s.is_empty()).unwrap_or(true) {\n            return Err(io::Error::new(\n                io::ErrorKind::Unsupported,\n                format!(\"the file name (it is {}) should not be empty\", p.display()),\n            ));\n        }\n        // create the parent dir if there isn't one.\n        // note: we may write to arbitrary directory here if the path contains things\n        // like '../' but internally the file name should be fully controlled by\n        // TiKV, so maybe it is OK?\n        if let Some(parent) = Path::new(name).parent() {\n            fs::create_dir_all(self.base.join(parent))\n                .await\n                // According to the man page mkdir(2), it returns EEXIST if there is already the dir.\n                // (However in practice, it doesn't fail in both Linux(CentOS 7) and macOS(12.2).)\n                // Ignore the `AlreadyExists` anyway for safety.\n                .or_else(|e| {\n                    if e.kind() == io::ErrorKind::AlreadyExists {\n                        Ok(())\n                    } else {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/tikv/tikv/blob/78aedc1c81ef3f7d8bacc6e9d09f56460f134937/components/external_storage/src/local.rs#L88-L124","documentation":"LocalStorage::write rejects empty file names — either an empty string or a path whose final component is empty (e.g. \"dir/\" or \".\"). Such a name identifies no writable file, so it fails with io::ErrorKind::Unsupported before touching the filesystem.","triggerScenarios":"Calling LocalStorage::write/save_file with name = \"\", \"dir/\", \".\", or any path whose file_name() component is empty or missing.","commonSituations":"String slicing/strip_prefix producing a trailing slash; format! or Path::join bugs leaving an empty basename; manifest entries with blank file names; automation generating paths from empty variables.","solutions":["Validate the name is non-empty and has a real file_name() component before calling write.","Fix upstream path construction so the basename is preserved after stripping prefixes.","Use Path::file_name() to assert a concrete file component exists; reject directories.","Check backup manifests/config for blank name fields and correct the producer."],"exampleFix":"// before\nlet name = path.strip_prefix(&base).unwrap(); // may be \"dir/\"\nstorage.write(name.to_str().unwrap(), reader, len).await?;\n// after\nlet name = path.strip_prefix(&base)?;\nassert!(name.file_name().map(|f| !f.is_empty()).unwrap_or(false));\nstorage.write(name.to_str().unwrap(), reader, len).await?;","handlingStrategy":"validation","validationCode":"// ensure a concrete file component exists before writing\nfn has_file_name(name: &str) -> bool {\n    Path::new(name).file_name().map(|f| !f.is_empty()).unwrap_or(false)\n}","typeGuard":"fn is_writable_name(name: &str) -> bool {\n    !name.is_empty() && Path::new(name).file_name().map(|f| !f.is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match storage.write(name, reader, len).await {\n    Err(e) if e.kind() == io::ErrorKind::Unsupported => {\n        // name empty or directory-like: fix name construction\n    }\n    r => r?,\n}","preventionTips":["Check for empty/trailing-slash names at every path-construction site","Never build names by slicing strings; use Path::join/strip_prefix","Validate manifest file-name fields are non-empty before processing","Avoid deriving names from possibly-empty config variables without defaults"],"tags":["path","validation","local-storage"],"backgroundTag":"invalid-file-path","analyzedSha":"78aedc1c81ef3f7d8bacc6e9d09f56460f134937","analyzedAt":"2026-09-03T23:31:32.398Z","contentChangedAt":"2026-09-03T23:31:32.398Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}