{"record":{"id":"d24db2db089c246a","repo":"Hmbown/CodeWhale","slug":"sub-agent-transcript-artifact-header-does-not-matc","errorCode":null,"errorMessage":"sub-agent transcript artifact header does not match agent {agent_id}","messagePattern":"sub-agent transcript artifact header does not match agent (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":7595,"sourceCode":"/// manager state root.\npub fn load_subagent_transcript_artifact(\n    state_root: &Path,\n    agent_id: &str,\n) -> Result<Vec<Message>> {\n    let state_root = normalize_subagent_workspace(state_root);\n    let path = checked_subagent_transcript_artifact_path(&state_root, agent_id)?;\n    let raw = read_subagent_state_file(&state_root, &path)?;\n    let mut lines = raw.lines();\n    let header_line = lines\n        .next()\n        .ok_or_else(|| anyhow!(\"sub-agent transcript artifact is empty\"))?;\n    let header: Value = serde_json::from_str(header_line)?;\n    if header.get(\"kind\").and_then(Value::as_str) != Some(\"subagent_transcript_header\")\n        || header.get(\"schema_version\").and_then(Value::as_u64)\n            != Some(u64::from(SUBAGENT_TRANSCRIPT_ARTIFACT_SCHEMA_VERSION))\n        || header.get(\"agent_id\").and_then(Value::as_str) != Some(agent_id)\n    {\n        return Err(anyhow!(\n            \"sub-agent transcript artifact header does not match agent {agent_id}\"\n        ));\n    }\n\n    let mut messages = Vec::new();\n    for line in lines.filter(|line| !line.trim().is_empty()) {\n        let record: Value = serde_json::from_str(line)?;\n        if record.get(\"kind\").and_then(Value::as_str) != Some(\"message\") {\n            return Err(anyhow!(\"unknown sub-agent transcript artifact record\"));\n        }\n        let index = record\n            .get(\"index\")\n            .and_then(Value::as_u64)\n            .and_then(|value| usize::try_from(value).ok())\n            .ok_or_else(|| anyhow!(\"sub-agent transcript message is missing its index\"))?;\n        if index != messages.len() {\n            return Err(anyhow!(\n                \"sub-agent transcript message index {index} does not follow {}\",","sourceCodeStart":7577,"sourceCodeEnd":7613,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/subagent/mod.rs#L7577-L7613","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-check the header before loading:\nlet raw = std::fs::read_to_string(&path)?;\nlet header: serde_json::Value = serde_json::from_str(raw.lines().next().unwrap())?;\nlet ok = header[\"kind\"] == \"subagent_transcript_header\"\n    && header[\"schema_version\"].as_u64() == Some(u64::from(SUBAGENT_TRANSCRIPT_ARTIFACT_SCHEMA_VERSION))\n    && header[\"agent_id\"] == agent_id;\nif !ok { /* wrong file or stale schema: regenerate */ }","typeGuard":"fn header_matches(header: &serde_json::Value, agent_id: &str, schema: u64) -> bool {\n    header.get(\"kind\").and_then(|v| v.as_str()) == Some(\"subagent_transcript_header\")\n        && header.get(\"schema_version\").and_then(|v| v.as_u64()) == Some(schema)\n        && header.get(\"agent_id\").and_then(|v| v.as_str()) == Some(agent_id)\n}","tryCatchPattern":"match load_subagent_transcript_artifact(&state_root, agent_id) {\n    Err(e) if e.to_string().contains(\"does not match agent\") => { /* check id + schema version, regenerate */ }\n    r => r?,\n}","preventionTips":["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."],"tags":["subagent","transcript","header-mismatch","schema-version","rust"],"backgroundTag":"schema-version-mismatch","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}