Hmbown/CodeWhale · error
sub-agent transcript artifact must have a parent directory
Error message
sub-agent transcript artifact must have a parent directory
What it means
`prepare_subagent_transcript_parent` requires the artifact path to have a parent directory (path.parent()); a degenerate path (empty or root-like) has none, so transcript creation is refused before any directory is made. Like 1211 this guards against malformed path construction rather than runtime state.
Source
Thrown at crates/tui/src/tools/subagent/mod.rs:7794
use std::os::unix::fs::OpenOptionsExt;
fs::OpenOptions::new()
.read(true)
.custom_flags(libc::O_NOFOLLOW)
.open(path)
.map_err(Into::into)
}
#[cfg(not(unix))]
fn open_subagent_state_file(path: &Path) -> Result<fs::File> {
fs::File::open(path).map_err(Into::into)
}
fn prepare_subagent_transcript_parent(state_root: &Path, path: &Path) -> Result<()> {
reject_root_relative_symlinks(state_root, path)?;
let parent = path
.parent()
.ok_or_else(|| anyhow!("sub-agent transcript artifact must have a parent directory"))?;
fs::create_dir_all(parent)?;
// Re-check after creation so a pre-existing component cannot redirect the
// private transcript outside the state root.
reject_root_relative_symlinks(state_root, path)?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
fs::set_permissions(parent, fs::Permissions::from_mode(0o700))?;
}
Ok(())
}
fn create_private_subagent_transcript(state_root: &Path, path: &Path, bytes: &[u8]) -> Result<()> {
prepare_subagent_transcript_parent(state_root, path)?;
let mut file = open_private_subagent_transcript(path, false)?;
file.write_all(bytes)?;
file.sync_all()?;
Ok(())View on GitHub (pinned to 0c42157ee5)
Solutions
- Construct artifact paths as state_root.join(transcripts_dir).join(file_name) with both parts non-empty.
- Reject empty directory components at the input boundary.
Defensive patterns
Strategy: validation
Validate before calling
let artifact = state_root.join("transcripts").join(format!("{agent_id}.jsonl"));
assert!(artifact.parent().is_some(), "artifact path needs a directory part"); Type guard
fn path_has_parent(p: &Path) -> bool {
p.parent().map_or(false, |parent| !parent.as_os_str().is_empty())
} Try / catch
match prepare_subagent_transcript_parent(&state_root, &path) {
Err(e) if e.to_string().contains("parent directory") => { /* rebuild path under an explicit transcripts dir */ }
r => r?,
} Prevention
- Always build artifact paths as root.join(dir).join(file), both parts non-empty.
When it happens
Trigger: Building a transcript path from user/model input that collapses to an empty or root-level path, or a PathBuf constructed without joining under the state root.
Common situations: Templating that yields "" for the directory part; API misuse calling the persister with a bare file name string.
Related errors
- sub-agent transcript history shrank from {} to {} messages
- sub-agent transcript artifact is empty
- sub-agent transcript artifact header does not match agent {a
- unknown sub-agent transcript artifact record
- sub-agent transcript message is missing its index
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/18cf283d8518026e.
Report an issue: GitHub.