tikv/tikv · error
the file name (it is {}) should not be empty
Error message
the file name (it is {}) should not be empty What it means
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.
Source
Thrown at components/external_storage/src/local.rs:106
async fn write(
&self,
name: &str,
reader: UnpinReader<'_>,
_content_length: u64,
) -> io::Result<()> {
let p = Path::new(name);
if p.is_absolute() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"the file name (it is {}) should never be absolute path",
p.display()
),
));
}
if name.is_empty() || p.file_name().map(|s| s.is_empty()).unwrap_or(true) {
return Err(io::Error::new(
io::ErrorKind::Unsupported,
format!("the file name (it is {}) should not be empty", p.display()),
));
}
// create the parent dir if there isn't one.
// note: we may write to arbitrary directory here if the path contains things
// like '../' but internally the file name should be fully controlled by
// TiKV, so maybe it is OK?
if let Some(parent) = Path::new(name).parent() {
fs::create_dir_all(self.base.join(parent))
.await
// According to the man page mkdir(2), it returns EEXIST if there is already the dir.
// (However in practice, it doesn't fail in both Linux(CentOS 7) and macOS(12.2).)
// Ignore the `AlreadyExists` anyway for safety.
.or_else(|e| {
if e.kind() == io::ErrorKind::AlreadyExists {
Ok(())
} else {View on GitHub (pinned to 78aedc1c81)
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.
Example fix
// before let name = path.strip_prefix(&base).unwrap(); // may be "dir/" storage.write(name.to_str().unwrap(), reader, len).await?; // after let name = path.strip_prefix(&base)?; assert!(name.file_name().map(|f| !f.is_empty()).unwrap_or(false)); storage.write(name.to_str().unwrap(), reader, len).await?;
Defensive patterns
Strategy: validation
Validate before calling
// ensure a concrete file component exists before writing
fn has_file_name(name: &str) -> bool {
Path::new(name).file_name().map(|f| !f.is_empty()).unwrap_or(false)
} Type guard
fn is_writable_name(name: &str) -> bool {
!name.is_empty() && Path::new(name).file_name().map(|f| !f.is_empty()).unwrap_or(false)
} Try / catch
match storage.write(name, reader, len).await {
Err(e) if e.kind() == io::ErrorKind::Unsupported => {
// name empty or directory-like: fix name construction
}
r => r?,
} Prevention
- 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
When it happens
Trigger: Calling LocalStorage::write/save_file with name = "", "dir/", ".", or any path whose file_name() component is empty or missing.
Common situations: 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.
Related errors
- the file name (it is {}) should never be absolute path
- backup metadata path has no file stem: {path}
- backup metadata path is not valid utf8: {path}
- cannot parse backup metadata path {path}: {err}
- invalid configurations for SAS token, err: {}
AI-assisted analysis of tikv/tikv@78aedc1c81 (2026-09-03).
Data as JSON: /api/errors/4cf1bee3f81bc6e5.
Report an issue: GitHub.