Hmbown/CodeWhale · error

sub-agent transcript message is missing its index

Error message

sub-agent transcript message is missing its index

What it means

A message record in the transcript artifact has no usable "index" field: it is missing, not a JSON u64, or too large for usize. The loader requires a dense integer index on every message record so ordering can be verified, so an unindexable record fails the whole load.

Source

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

            != 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"))?,
        )?;
        messages.push(message);
    }
    Ok(messages)
}

fn remove_subagent_transcript_artifact(state_root: &Path, agent_id: &str) -> Result<bool> {

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Ensure every message record carries an unsigned integer "index" field.
  2. Repair the offending line by adding the correct dense index, or regenerate the artifact.
  3. Always write artifacts through the persister, which stamps index automatically.
Defensive patterns

Strategy: try-catch

Validate before calling

for (i, line) in raw.lines().enumerate().skip(1) {
    let v: serde_json::Value = serde_json::from_str(line)?;
    if v.get("index").and_then(|x| x.as_u64()).is_none() {
        // line {i} lacks a u64 index: repair before loading
    }
}

Type guard

fn record_has_u64_index(v: &serde_json::Value) -> bool {
    v.get("index").and_then(|x| x.as_u64()).is_some()
}

Try / catch

match load_subagent_transcript_artifact(&state_root, agent_id) {
    Err(e) if e.to_string().contains("missing its index") => { /* add dense index to offending line */ }
    r => r?,
}

Prevention

When it happens

Trigger: Records written without the index field (external writer or older format), index serialized as a string or negative number, or manual edits that dropped the field.

Common situations: Hand-repaired artifacts; third-party code writing message lines; serialization changes that emit index as a different JSON type.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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