{"record":{"id":"d56276e5b18301a8","repo":"Hmbown/CodeWhale","slug":"sub-agent-transcript-artifact-is-empty","errorCode":null,"errorMessage":"sub-agent transcript artifact is empty","messagePattern":"sub-agent transcript artifact is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":7588,"sourceCode":"        &subagent_transcript_artifact_relative_path(agent_id),\n    )\n}\n\n/// Read the complete structured worker chat for the TUI Open action. The path\n/// is derived from `agent_id` rather than accepted from handle JSON, so a\n/// corrupted or model-supplied payload cannot redirect the reader outside the\n/// 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","sourceCodeStart":7570,"sourceCodeEnd":7606,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/subagent/mod.rs#L7570-L7606","documentation":"`load_subagent_transcript_artifact` read the transcript file but `raw.lines()` produced no first line — the artifact is empty. The loader requires at minimum a header line (kind=subagent_transcript_header), so a zero-byte file cannot be a valid transcript. This almost always means the file was truncated or created by something other than the persister.","triggerScenarios":"Artifact truncated to zero bytes by a crashed/interrupted write, external tooling overwriting the state file, a full disk, or a test fixture that created an empty file at the expected path.","commonSituations":"Hard kill during child spawn; state dir on a full or flaky disk; backup/sync/editor software touching state files; manually crafted fixtures.","solutions":["Check the artifact's size under the sub-agent state root; restore from backup, or delete it so the manager recreates it on the next spawn.","Re-run the sub-agent task — transcripts are per-agent artifacts and regenerate on rerun.","Keep external processes from writing the state dir; all writes should go through the persister's path."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let path = checked_subagent_transcript_artifact_path(&state_root, agent_id)?;\nlet meta = std::fs::symlink_metadata(&path)?;\nif meta.len() == 0 { /* empty artifact: regenerate instead of loading */ }","typeGuard":"fn artifact_is_loadable(raw: &str) -> bool {\n    raw.lines().next().is_some()\n}","tryCatchPattern":"match load_subagent_transcript_artifact(&state_root, agent_id) {\n    Err(e) if e.to_string().contains(\"artifact is empty\") => { /* delete + respawn */ }\n    r => r?,\n}","preventionTips":["Write artifacts atomically; never truncate-then-write.","Keep external processes out of the sub-agent state root.","Check state-dir disk space on long-running hosts."],"tags":["subagent","transcript","empty-file","corruption","rust"],"backgroundTag":"corrupt-transcript-artifact","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}