Hmbown/CodeWhale · error · std::io::Error
snapshot dir has no parent
Error message
snapshot dir has no parent
What it means
InvalidInput returned when snapshot_git_dir(&work_tree).parent() is None, i.e. the computed snapshot git-dir path has no parent component. A normal snapshot dir like <workspace>/.<something> always has the workspace as its parent, so this branch firing means path construction produced a root-equivalent path — an internal invariant violation rather than an expected runtime condition.
Source
Thrown at crates/tui/src/snapshot/repo.rs:271
// is intentional: paying a workspace walk on every snapshot
// would defeat the purpose of the cap, and a workspace
// that fit on first init is allowed to grow within the
// existing repo's `MAX_SNAPSHOT_SIZE_MB` budget. Users on
// workspaces that grew past the cap mid-session get the
// existing aggressive-pruning path in `snapshot()`.
if estimate_workspace_size_bounded(&work_tree, cap_bytes).is_none() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"workspace too large for snapshots (over {} GB of non-excluded content or > {} entries): {}\n raise `[snapshots] max_workspace_gb` in config.toml (or set it to 0 to disable the cap) if you want snapshots on this workspace.",
cap_bytes / (1024 * 1024 * 1024),
SIZE_WALK_MAX_ENTRIES,
work_tree.display()
),
));
}
let parent = git_dir.parent().ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, "snapshot dir has no parent")
})?;
std::fs::create_dir_all(parent)?;
// `git init` here uses the parent directory as the work tree
// and stores metadata in `.git`. We then continue to use
// explicit `--git-dir` / `--work-tree` flags for every other
// command so behaviour is invariant of cwd.
let init = crate::dependencies::Git::command()
.ok_or_else(|| io_other("git not found on PATH"))?
.arg("init")
.arg("--quiet")
.arg(parent)
.output()
.map_err(|e| io_other(format!("failed to spawn git init: {e}")))?;
if !init.status.success() {
return Err(io_other(format!(
"git init failed: {}",
String::from_utf8_lossy(&init.stderr).trim()
)));View on GitHub (pinned to 0c42157ee5)
Solutions
- Verify the workspace path you passed is a normal absolute directory, not a root-like path
- Check for local modifications to snapshot_git_dir / repo.rs that change the snapshot dir layout
- If it reproduces on an unmodified build, capture the exact workspace path and report a bug — this is a defensive invariant
Defensive patterns
Strategy: try-catch
Validate before calling
let ws = workspace.canonicalize().unwrap_or_else(|_| workspace.to_path_buf()); assert!(ws.parent().is_some(), "workspace must not be the filesystem root");
Type guard
fn is_snapshot_dir_invariant(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("snapshot dir has no parent")
} Try / catch
match repo::open_or_init_with_cap(&ws, cap) {
Ok(r) => Ok(r),
Err(e) if is_snapshot_dir_invariant(&e) => report_bug_with_path(&ws, &e), // not a user-fixable state
Err(e) => Err(e),
} Prevention
- Reject root-like workspace paths at your own boundary — cheap and removes the whole class
- Treat this specific message as an internal bug report trigger, not a configuration problem
When it happens
Trigger: Effectively unreachable through normal API use; would require the workspace canonicalization and snapshot_git_dir to yield a path like "/" (for example a pathological custom workspace path or a regression in snapshot_git_dir).
Common situations: Almost never seen in the wild; appears only with degenerate paths (workspace passed as "/" after canonicalize, which the earlier safety guard at line 238 already rejects) or after a code change to snapshot dir naming.
Related errors
- Persistent service {id} disappeared before commit
- Persistent service {id} has no releasable process id
- Persistent service {id} disappeared during commit
- Persistent service {id} lost its process id
- workspace snapshots are disabled for {reason}: {}
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/951e4ecd5ec7c152.
Report an issue: GitHub.