Hmbown/CodeWhale · error · anyhow::Error
sub-agent transcript artifact is not a regular file
Error message
sub-agent transcript artifact is not a regular file: {} What it means
Before deleting a sub-agent transcript artifact, the code checks it with `fs::symlink_metadata` and requires the entry to be a regular file — not a symlink, directory, FIFO, or other special file. If the path exists but is not a plain file, deletion is refused to avoid following or clobbering unexpected filesystem objects.
Solutions
- Remove the symlink or directory at that path manually and let the library recreate a regular file.
- Point the sub-agent state root at a location where the artifact path is a plain file.
- If the symlink is intentional, copy the target's contents into a regular file at the artifact path first.
- Check that container/volume mounts are not substituting special file types at the state path.
Example fix
// before: transcript path is a symlink ls -l ~/.codewhale/state/transcripts/abc.jsonl # -> symlink // after: replace with a regular file rm ~/.codewhale/state/transcripts/abc.jsonl cp /shared/abc.jsonl ~/.codewhale/state/transcripts/abc.jsonl
Defensive patterns
Strategy: validation
Validate before calling
use std::fs;
fn is_regular_file(p: &std::path::Path) -> bool {
fs::symlink_metadata(p).map(|m| m.file_type().is_file()).unwrap_or(false)
}
// only call the delete/cleanup API when is_regular_file(path) Try / catch
match cleanup_transcript(path) {
Ok(removed) => { /* proceed */ }
Err(e) if e.to_string().contains("not a regular file") => {
// remove the symlink/dir yourself, then retry
}
Err(e) => return Err(e),
} Prevention
- Do not symlink transcript artifacts into shared storage.
- Keep the state root free of directories/special files at artifact paths.
- Audit container volume mounts for substituted file types.
When it happens
Trigger: Attempting transcript cleanup on a path that resolves to a symlink or a directory instead of a regular file; the check `metadata.file_type().is_symlink() || !metadata.file_type().is_file()` fires.
Common situations: A user replaced the transcript file with a symlink to shared storage; a directory was created where the artifact should live; tmpfs or container volume mounts produced non-regular entries.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- CodewhalePet/1
- late usage store must be a real directory
- Session goal must be a regular file
- Session goal must be a regular file
- Session goal store must be a real directory
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b5a34e82248e57cd.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:8609
.cloned()
.ok_or_else(|| anyhow!("sub-agent transcript record is missing its message"))?,
)?;
messages.push(message);
}
Ok(messages)
}
fn remove_subagent_transcript_artifact(state_root: &Path, agent_id: &str) -> Result<bool> {
let state_root = normalize_subagent_workspace(state_root);
let path = checked_subagent_transcript_artifact_path(&state_root, agent_id)?;
reject_root_relative_symlinks(&state_root, &path)?;
let metadata = match fs::symlink_metadata(&path) {
Ok(metadata) => metadata,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(false),
Err(err) => return Err(err.into()),
};
if metadata.file_type().is_symlink() || !metadata.file_type().is_file() {
return Err(anyhow!(
"sub-agent transcript artifact is not a regular file: {}",
path.display()
));
}
fs::remove_file(path)?;
Ok(true)
}
#[cfg(test)]
pub(crate) fn write_subagent_transcript_artifact_for_test(
state_root: &Path,
agent_id: &str,
messages: &[Message],
) -> Result<PathBuf> {
let mut writer = SubAgentTranscriptArtifactWriter::create(state_root, agent_id)?;
writer.sync_messages(messages, true)?;
Ok(writer.path)
}View on GitHub (pinned to 73e0f67d83)