Hmbown/CodeWhale · error · std::io::Error
session file missing parseable `metadata` block
Error message
session file missing parseable `metadata` block
What it means
Returned as io::ErrorKind::InvalidData when the session manager loads a session file whose top-level `metadata` block cannot be parsed. The loader first tries to extract metadata from an already-read prefix, then reads the remainder of the file and retries with the full buffer; this error means both attempts failed. The file on disk is therefore genuinely truncated or its metadata record is corrupted beyond what extract_top_level_metadata accepts.
Source
Thrown at crates/tui/src/session_manager.rs:1661
const PREFIX_BYTES: usize = 64 * 1024;
let mut file = fs::File::open(path)?;
let mut buf = Vec::with_capacity(PREFIX_BYTES);
file.by_ref()
.take(PREFIX_BYTES as u64)
.read_to_end(&mut buf)?;
if let Some(metadata) = extract_top_level_metadata(&buf) {
return Ok(metadata);
}
// Metadata wasn't extractable from the prefix (truncated mid-block,
// unusual key ordering, etc.). Read the rest and try again with the
// full buffer before giving up.
let mut rest = Vec::new();
file.read_to_end(&mut rest)?;
buf.extend_from_slice(&rest);
extract_top_level_metadata(&buf).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
"session file missing parseable `metadata` block",
)
})
}
/// Delete a session by ID
pub fn delete_session(&self, id: &str) -> std::io::Result<()> {
let path = self.validated_session_path(id)?;
self.save_session_goal(id, None)?;
fs::remove_file(path)?;
self.clear_session_boot_owner(id);
let session_dir = self.sessions_dir.join(id.trim());
if session_dir.exists() {
fs::remove_dir_all(session_dir)?;
}
Ok(())
}View on GitHub (pinned to 0c42157ee5)
Solutions
- Restore the affected session file from a backup or the previous synced copy
- If the session is disposable, delete or move the file out of the sessions directory so the manager regenerates a clean one
- Check free disk space and filesystem health to stop ongoing truncation during saves
- If the metadata line looks well-formed but still fails extraction, preserve the file and report a bug against extract_top_level_metadata
Example fix
// before
let meta = manager.session_metadata(id)?; // one bad file aborts the whole listing
// after
let meta = match manager.session_metadata(id) {
Ok(m) => m,
Err(e) if e.kind() == std::io::ErrorKind::InvalidData => continue, // skip corrupt file, keep listing
Err(e) => return Err(e),
}; Defensive patterns
Strategy: try-catch
Validate before calling
let raw = std::fs::read_to_string(&path)?;
let looks_complete = raw.lines().any(|l| l.contains("\"metadata\""));
if !looks_complete {
// quarantine the file before the session loader rejects it
let _ = std::fs::rename(&path, path.with_extension("corrupt"));
} Type guard
fn is_unparseable_session_metadata(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::InvalidData
&& e.to_string().contains("missing parseable `metadata` block")
} Try / catch
match manager.load_session(id) {
Ok(s) => Ok(Some(s)),
Err(e) if is_unparseable_session_metadata(&e) => {
tracing::warn!(%id, "skipping corrupt session file");
Ok(None) // degrade gracefully, keep the session list usable
}
Err(e) => Err(e),
} Prevention
- Treat a failed/disk-full session save as fatal and surface it instead of leaving truncated files
- Back up the sessions directory before version upgrades
- Keep sync tools from touching the sessions directory while the app is running
When it happens
Trigger: Resuming or listing a session whose .jsonl file was truncated mid-write (process kill, power loss, disk full during save), or whose metadata line was hand-edited, reordered, or written by an incompatible older format, so neither the prefix parse nor the full-buffer re-parse succeeds.
Common situations: App crashed while saving a session; disk-full during session write; sessions directory partially copied between machines or mutated by sync/backup tools; session files from a much older Codewhale version after an upgrade.
Related errors
- ${name} is unavailable in Workflow scripts: runs must be det
- new Date()/Date() is unavailable in Workflow scripts: runs m
- parallel(): expected an array of thunks
- app-server auth token cannot be empty
- refusing non-loopback app-server bind without explicit auth
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/d1b583c50617d8c8.
Report an issue: GitHub.