clockworklabs/SpacetimeDB · error · io::Error

repo {}: error getting file metadata for segment {}: {}

Error message

repo {}: error getting file metadata for segment {}: {}

What it means

While checking whether a segment file already exists, fs::metadata on the segment path returned an error other than NotFound (which is the normal, handled 'segment absent' case). The original ErrorKind and message are passed through, so the real cause - PermissionDenied, EIO, path issues - is in the inner error text.

Source

Thrown at crates/commitlog/src/repo/fs.rs:266

                    warn!("repo {}: failed to remove {}: {}", self, lock_path.display(), e);
                }
            },
        );

        // Check whether the segment already exists.
        // Overwrite it if its length is zero.
        match fs::metadata(&path) {
            Ok(stat) => {
                if stat.len() > 0 {
                    return Err(io::Error::new(
                        io::ErrorKind::AlreadyExists,
                        format!("repo {}: segment {} already exists and is non-empty", self, offset),
                    ));
                }
            }
            Err(e) => {
                if e.kind() != io::ErrorKind::NotFound {
                    return Err(io::Error::new(
                        e.kind(),
                        format!(
                            "repo {}: error getting file metadata for segment {}: {}",
                            self, offset, e
                        ),
                    ));
                }
            }
        }

        // The segment file either does not exist, or is of length zero.
        // Write the header to a temporary file and atomically move it into place.
        let mut tmp = tempfile::Builder::new().make_in(&self.root.0, |tmp_path| {
            File::options().read(true).write(true).create_new(true).open(tmp_path)
        })?;
        header.write(&mut tmp)?;
        tmp.as_file_mut().sync_all()?;
        let segment = tmp.persist(path)?;

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Read the inner {e} and its ErrorKind: fix directory permissions or path components accordingly
  2. If the kind is EIO, check device/dmesg health and remount the filesystem
  3. Reproduce as the same user with `stat <segment path>` to confirm it is environmental
Defensive patterns

Strategy: try-catch

Validate before calling

// smoke-test the path before opening the log
std::fs::metadata(&dir).and_then(|m| {
    if m.is_dir() { Ok(()) } else { Err(io::Error::new(io::ErrorKind::NotFound, "not a directory")) }
})?;

Type guard

fn is_segment_metadata_error(e: &io::Error) -> bool {
    e.to_string().contains("error getting file metadata for segment")
}

Try / catch

match result {
    Ok(v) => v,
    Err(e) if is_segment_metadata_error(&e) => {
        // surface the inner kind (PermissionDenied, EIO, ...) for the operator
        return Err(io::Error::new(e.kind(), format!("stat failed on log segment: {e}")));
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: create_segment stats <dir>/<segment> and the stat itself fails: missing execute permission on a path component, an I/O error from the device, or a path that exceeds filesystem limits.

Common situations: Running as a non-root user on root-owned directories; flaky NFS/FUSE mounts returning EIO on stat; exotic path configurations.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/c69f90fd0b48d3aa. Report an issue: GitHub.