spacedriveapp/spacedrive · error · FileIOError

Cannot determine parent directory

Error message

Cannot determine parent directory

What it means

Thumbnailer::process writes a webp thumbnail to output_thumbnail_path and first resolves parent() to create the directory tree. parent() returns None only for paths with no parent component: the empty path or the root '/'. The FileIOError (ErrorKind::InvalidInput) is constructed before any I/O, so this is a caller-argument bug, not an environment failure.

Source

Thrown at crates/ffmpeg/src/thumbnailer.rs:29

/// `Thumbnailer` struct holds data from a `ThumbnailerBuilder`, exposing methods
/// to generate thumbnails from video files.
#[derive(Debug, Clone)]
pub struct Thumbnailer {
	builder: ThumbnailerBuilder,
}

impl Thumbnailer {
	/// Processes an video input file and write to file system a thumbnail with webp format
	pub(crate) async fn process(
		&self,
		video_file_path: impl AsRef<Path> + Send,
		output_thumbnail_path: impl AsRef<Path> + Send,
	) -> Result<(), Error> {
		let output_thumbnail_path = output_thumbnail_path.as_ref();
		let path = output_thumbnail_path.parent().ok_or_else(|| {
			FileIOError::from_std_io_err(
				output_thumbnail_path,
				io::Error::new(
					io::ErrorKind::InvalidInput,
					"Cannot determine parent directory",
				),
			)
		})?;

		fs::create_dir_all(path)
			.await
			.map_err(|e| FileIOError::from_std_io_err(path, e))?;

		let webp = self.process_to_webp_bytes(video_file_path).await?;
		let mut file = fs::File::create(output_thumbnail_path)
			.await
			.map_err(|e: io::Error| FileIOError::from_std_io_err(output_thumbnail_path, e))?;

		file.write_all(&webp)
			.await
			.map_err(|e| FileIOError::from_std_io_err(output_thumbnail_path, e))?;

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Log the exact output_thumbnail_path reaching process(): it is empty or '/'
  2. Fix the caller to always build a full file path: dir.join(format!("{}.webp", file_id))
  3. Validate the thumbnail directory setting is non-empty before enqueueing thumbnail jobs

Example fix

// before: empty config yields Path::new("")
let out = PathBuf::from(cfg.thumbnail_dir); // ""
thumb.process(input, out).await?;

// after: validate filename presence before calling
let out = cfg.thumbnail_dir.join(format!("{}.webp", id));
assert!(out.file_name().is_some(), "thumbnail path needs a filename: {}", out.display());
thumb.process(input, out).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Before calling Thumbnailer::process, require a non-root path with a file name
fn valid_thumbnail_path(p: &Path) -> bool {
    p.parent().is_some() && p.file_name().is_some() && !p.as_os_str().is_empty()
}
assert!(valid_thumbnail_path(&out));

Type guard

fn has_parent_and_filename(p: &Path) -> bool {
    !p.as_os_str().is_empty() && p != Path::new("/") && p.file_name().is_some()
}

Try / catch

// Thumbnailer::process returns Result; match on the FileIOError and log the offending path
if let Err(e) = thumb.process(input, &out).await {
    tracing::error!(path = %out.display(), error = %e, "thumbnail failed; check path construction");
}

Prevention

When it happens

Trigger: Passing Path::new("") or Path::new("/") as the thumbnail output path; building the path from an empty config field so the join collapses to nothing; a path-construction bug that drops the filename component.

Common situations: Thumbnail job enqueued with an unset thumbnail_dir setting; empty string from config for the output path; test harness passing a literal empty path.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/804effeb9dcea5a3. Report an issue: GitHub.