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
- Log the exact output_thumbnail_path reaching process(): it is empty or '/'
- Fix the caller to always build a full file path: dir.join(format!("{}.webp", file_id))
- 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
- Never build output paths from unvalidated config strings
- Centralize thumbnail path construction in one helper that asserts file_name() presence
- Reject empty thumbnail_dir at config load time
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.