Hmbown/CodeWhale · error
sub-agent transcript artifact header does not match agent {a
Error message
sub-agent transcript artifact header does not match agent {agent_id} What it means
`load_subagent_transcript_artifact` validates the JSON header line against three invariants: kind must be "subagent_transcript_header", schema_version must equal SUBAGENT_TRANSCRIPT_ARTIFACT_SCHEMA_VERSION, and agent_id must equal the requested agent. Any mismatch refuses the load rather than deserializing a file that is not exactly this agent's artifact at this build's schema version.
Source
Thrown at crates/tui/src/tools/subagent/mod.rs:7595
/// manager state root.
pub fn load_subagent_transcript_artifact(
state_root: &Path,
agent_id: &str,
) -> Result<Vec<Message>> {
let state_root = normalize_subagent_workspace(state_root);
let path = checked_subagent_transcript_artifact_path(&state_root, agent_id)?;
let raw = read_subagent_state_file(&state_root, &path)?;
let mut lines = raw.lines();
let header_line = lines
.next()
.ok_or_else(|| anyhow!("sub-agent transcript artifact is empty"))?;
let header: Value = serde_json::from_str(header_line)?;
if header.get("kind").and_then(Value::as_str) != Some("subagent_transcript_header")
|| header.get("schema_version").and_then(Value::as_u64)
!= Some(u64::from(SUBAGENT_TRANSCRIPT_ARTIFACT_SCHEMA_VERSION))
|| header.get("agent_id").and_then(Value::as_str) != Some(agent_id)
{
return Err(anyhow!(
"sub-agent transcript artifact header does not match agent {agent_id}"
));
}
let mut messages = Vec::new();
for line in lines.filter(|line| !line.trim().is_empty()) {
let record: Value = serde_json::from_str(line)?;
if record.get("kind").and_then(Value::as_str) != Some("message") {
return Err(anyhow!("unknown sub-agent transcript artifact record"));
}
let index = record
.get("index")
.and_then(Value::as_u64)
.and_then(|value| usize::try_from(value).ok())
.ok_or_else(|| anyhow!("sub-agent transcript message is missing its index"))?;
if index != messages.len() {
return Err(anyhow!(
"sub-agent transcript message index {index} does not follow {}",View on GitHub (pinned to 0c42157ee5)
Solutions
- Confirm you are loading the artifact for the same agent_id you spawned (no normalization drift).
- After upgrading builds, delete stale artifacts and let them regenerate instead of reusing files from an old schema version.
- When forking or renaming agents, write new artifacts with a fresh header rather than copying files.
- Verify the header line's schema_version matches SUBAGENT_TRANSCRIPT_ARTIFACT_SCHEMA_VERSION in the running build.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check the header before loading:
let raw = std::fs::read_to_string(&path)?;
let header: serde_json::Value = serde_json::from_str(raw.lines().next().unwrap())?;
let ok = header["kind"] == "subagent_transcript_header"
&& header["schema_version"].as_u64() == Some(u64::from(SUBAGENT_TRANSCRIPT_ARTIFACT_SCHEMA_VERSION))
&& header["agent_id"] == agent_id;
if !ok { /* wrong file or stale schema: regenerate */ } Type guard
fn header_matches(header: &serde_json::Value, agent_id: &str, schema: u64) -> bool {
header.get("kind").and_then(|v| v.as_str()) == Some("subagent_transcript_header")
&& header.get("schema_version").and_then(|v| v.as_u64()) == Some(schema)
&& header.get("agent_id").and_then(|v| v.as_str()) == Some(agent_id)
} Try / catch
match load_subagent_transcript_artifact(&state_root, agent_id) {
Err(e) if e.to_string().contains("does not match agent") => { /* check id + schema version, regenerate */ }
r => r?,
} Prevention
- Don't copy state dirs between builds with different schema versions.
- Load artifacts only with the agent_id that created them.
- After upgrades, let artifacts regenerate rather than reusing old files.
When it happens
Trigger: Loading with an agent_id whose artifact belongs to a different agent; artifact written by an older or newer build whose schema_version differs; a hand-edited or reformatted header; state dirs copied between installs.
Common situations: Version upgrades that bump the transcript schema; copying/migrating state directories between machines or builds; agent-id normalization differences (case, prefixes) between writer and reader.
Related errors
- sub-agent transcript history shrank from {} to {} messages
- sub-agent transcript artifact is empty
- unknown sub-agent transcript artifact record
- sub-agent transcript message is missing its index
- sub-agent transcript message index {index} does not follow {
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/d24db2db089c246a.
Report an issue: GitHub.