Hmbown/CodeWhale · error

unknown sub-agent transcript artifact record

Error message

unknown sub-agent transcript artifact record

What it means

While parsing lines after the header, `load_subagent_transcript_artifact` found a line whose JSON "kind" field is not "message". Only message records are valid in a transcript artifact; any other record kind (or a stray JSON line from another writer) aborts the load.

Source

Thrown at crates/tui/src/tools/subagent/mod.rs:7604

    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 {}",
                messages.len()
            ));
        }
        let message = serde_json::from_value::<Message>(
            record
                .get("message")
                .cloned()
                .ok_or_else(|| anyhow!("sub-agent transcript record is missing its message"))?,
        )?;

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Inspect the artifact for the offending line (first line after the header whose kind != "message") and remove or fix it.
  2. Ensure only the sub-agent persister writes transcript artifacts; move logs elsewhere.
  3. Regenerate the artifact by re-running the sub-agent if manual repair is impractical.
Defensive patterns

Strategy: try-catch

Validate before calling

// Scan artifact lines for foreign records before loading:
for (i, line) in raw.lines().enumerate().skip(1) {
    if let Ok(v) = serde_json::from_str::<serde_json::Value>(line) {
        if v["kind"].as_str() != Some("message") { /* line {i} is foreign: fix or remove */ }
    }
}

Type guard

fn line_is_message_record(line: &str) -> bool {
    serde_json::from_str::<serde_json::Value>(line)
        .map(|v| v.get("kind").and_then(|k| k.as_str()) == Some("message"))
        .unwrap_or(false)
}

Try / catch

match load_subagent_transcript_artifact(&state_root, agent_id) {
    Err(e) if e.to_string().contains("unknown sub-agent transcript artifact record") => { /* locate + strip foreign line, retry once */ }
    r => r?,
}

Prevention

When it happens

Trigger: A JSONL line appended by a different producer (structured logs, tool output) into the artifact; mixed-format artifacts from a partial migration; hand-appended diagnostic records.

Common situations: State files shared with logging output; scripts that append to files under the state root; artifact formats changed between versions leaving old-style records in place.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/c0498d7ff9b2f202. Report an issue: GitHub.