quickwit-oss/quickwit · error · io::Error (InvalidData)

Invalid file name in path {path:?}

Error message

Invalid file name in path {path:?}

What it means

When building a FilePayload, the code takes a filesystem path and extracts its final path component as the upload file name. If the path has no file name — e.g. it ends in '..' or is a bare root like '/' — `path.file_name()` returns None and this io::Error with ErrorKind::InvalidData is constructed. It is an internal guard: callers of add_file are expected to pass concrete file paths, not directories or traversal components.

Source

Thrown at quickwit/quickwit-storage/src/split.rs:186

        Ok(offsets)
    }

    /// Adds the payload to the bundle file.
    pub fn add_payload(&mut self, file_name: String, payload: Box<dyn PutPayload>) {
        let range = self.current_offset as u64..self.current_offset as u64 + payload.len();
        self.current_offset += payload.len() as usize;
        self.payloads.push((file_name, payload, range));
    }

    /// Adds the file to the bundle file.
    pub fn add_file(&mut self, path: &Path) -> io::Result<()> {
        let file = std::fs::metadata(path)?;
        let file_name = path
            .file_name()
            .and_then(std::ffi::OsStr::to_str)
            .map(ToOwned::to_owned)
            .ok_or_else(|| {
                io::Error::new(
                    io::ErrorKind::InvalidData,
                    format!("Invalid file name in path {path:?}"),
                )
            })?;

        let file_payload = FilePayload {
            path: path.to_owned(),
            len: file.len(),
        };

        self.add_payload(file_name, Box::new(file_payload));

        Ok(())
    }

    /// Writes the bundle file ranges at the end of the bundle file.
    pub fn finalize(self, hotcache: &[u8]) -> anyhow::Result<SplitPayload> {
        let enable_footer_trailer =

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Pass the full path to a concrete file (e.g. <split_dir>/hotcache) rather than its parent directory.
  2. Strip trailing slashes and resolve '..' components before calling add_file (use PathBuf::canonicalize).
  3. Ensure the path is valid UTF-8 on Unix (or rename the file) since file_name() must convert via OsStr::to_str.

Example fix

// before
add_file(&split_dir.join("..")).await?;
// after
let hotcache_path = split_dir.canonicalize()?.join("hotcache");
add_file(&hotcache_path).await?;
Defensive patterns

Strategy: validation

Validate before calling

let path = PathBuf::from(raw);
assert!(path.file_name().is_some(), "path must end in a real file name: {raw:?}");
let path = path.canonicalize()?;

Type guard

fn has_file_name(path: &Path) -> bool { path.file_name().map(|n| n.to_str().is_some()).unwrap_or(false) }

Prevention

When it happens

Trigger: Calling add_file (via get_split_payload) with a path whose last component is not a regular file name: a trailing slash or '..' component, a path like "/" or "/tmp/..", or a non-UTF-8 final component (OsStr::to_str fails).

Common situations: Building split payloads from programmatically joined paths where a directory was passed instead of the hotcache/anchor file inside it; shell/script variable expansions leaving a trailing slash; non-UTF-8 filenames on Linux.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/7bedb06259f7229b. Report an issue: GitHub.