xai-org/grok-build · error · std::io::Error
summary.json is empty (0 bytes): {}
Error message
summary.json is empty (0 bytes): {} What it means
read_summary reads a session's summary.json and rejects a zero-length file before attempting JSON parsing. This library writes summary.json atomically, so a 0-byte file means the file was truncated or created by a non-atomic writer (or a crash/interrupted write left a stub). The io::ErrorKind::InvalidData error carries the file path to help locate the corrupt file.
Source
Thrown at crates/codegen/xai-grok-shell/src/session/storage/summary_write.rs:408
let mut summary = read_summary(summary_path)?;
let absent_title_applied = summary.apply_patch(patch, Utc::now());
write_summary_atomic(summary_path, &summary)?;
Ok(absent_title_applied)
}
fn open_lock_file(path: &Path) -> io::Result<File> {
OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(false)
.open(path)
}
fn read_summary(path: &Path) -> io::Result<Summary> {
let bytes = std::fs::read(path)?;
if bytes.is_empty() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("summary.json is empty (0 bytes): {}", path.display()),
));
}
serde_json::from_slice::<Summary>(&bytes)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
fn write_summary_atomic(summary_path: &Path, summary: &Summary) -> io::Result<()> {
let bytes = serde_json::to_vec_pretty(summary)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
crate::session::storage::write_bytes_atomic(summary_path, &bytes)
}
#[cfg(test)]
thread_local! {
static RESTORE_MTIME_FAULT: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}View on GitHub (pinned to bc7f02eddd)
Solutions
- Delete the empty summary.json (or restore it from backup) so the session can regenerate it on next write
- Re-run the operation; readers that fail on one session's empty summary are usually scanning multiple sessions — ensure the code skips unreadable sessions instead of aborting
- Verify writes go through write_summary_atomic/write_bytes_atomic, never plain fs::write to the final path
- Check disk space and filesystem health if truncation happened repeatedly
Example fix
// before
let summary = read_summary(&path)?;
// after
let summary = match read_summary(&path) {
Ok(s) => s,
Err(e) if e.kind() == io::ErrorKind::InvalidData => { /* skip/log corrupt summary */ continue; }
Err(e) => return Err(e),
}; Defensive patterns
Strategy: try-catch
Validate before calling
let meta = std::fs::metadata(&path)?;
if meta.len() == 0 { /* skip or delete corrupt summary */ } Type guard
fn is_readable_summary(path: &Path) -> bool {
std::fs::read(path).map(|b| !b.is_empty()).unwrap_or(false)
} Try / catch
match read_summary(&path) {
Ok(s) => s,
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
let _ = std::fs::remove_file(&path); // drop corrupt file, regenerate later
Summary::default()
}
Err(e) => return Err(e),
} Prevention
- Always write summary.json via the atomic write helpers, never plain fs::write
- When scanning multiple sessions, skip InvalidData errors instead of aborting the scan
- Monitor disk space; truncation is often disk-full during write
- Keep backups or regenerate summaries instead of failing hard on one corrupt file
When it happens
Trigger: Calling read_summary (directly or via most_recent_local_summary_for_cwd_in_view, repair_worktree_identity, read_modify_write, or the auto-title paths) on a summary.json that exists but is 0 bytes — e.g. after a crash during a legacy non-atomic write, an external tool touching the file, or a filesystem sync that truncated it.
Common situations: Disk-full during an old non-atomic write; a user or backup tool creating an empty summary.json; crash between file creation and content flush; cloning/syncing session dirs with a sync tool that creates placeholder empty files.
Related errors
- failed to replace {}: {e}
- InvalidInput
- Compaction checkpoint file corrupt: {checkpoint_path}. Canno
- <serde_json deserialization error for summary.json>
- <serde_json serialization error for Summary>
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/29720e0747ea8ea7.
Report an issue: GitHub.