Hmbown/CodeWhale · error
sub-agent transcript message index {index} does not follow {
Error message
sub-agent transcript message index {index} does not follow {} What it means
Each message record's index must equal the number of messages already read (dense 0-based sequence). This error fires when a record's index skips ahead, repeats, or is out of order — the loader refuses sequences with gaps or duplicates because they can hide dropped or duplicated messages.
Source
Thrown at crates/tui/src/tools/subagent/mod.rs:7612
{
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> {
let state_root = normalize_subagent_workspace(state_root);
let path = checked_subagent_transcript_artifact_path(&state_root, agent_id)?;View on GitHub (pinned to 0c42157ee5)
Solutions
- Repair the artifact so indexes run densely 0..n with no gaps or repeats.
- Regenerate the transcript by re-running the sub-agent when manual renumbering is risky.
- Never append to an artifact from more than one process; only the owning persister may write.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify dense 0-based ordering before loading:
for (expected, line) in raw.lines().skip(1).filter(|l| !l.trim().is_empty()).enumerate() {
let v: serde_json::Value = serde_json::from_str(line)?;
if v["index"].as_u64() != Some(expected as u64) { /* gap/ordering issue at {expected} */ }
} Type guard
fn indexes_are_dense(lines: impl Iterator<Item = String>) -> bool {
lines.enumerate().all(|(i, l)| {
serde_json::from_str::<serde_json::Value>(&l)
.map(|v| v["index"].as_u64() == Some(i as u64))
.unwrap_or(false)
})
} Try / catch
match load_subagent_transcript_artifact(&state_root, agent_id) {
Err(e) if e.to_string().contains("does not follow") => { /* renumber 0..n or regenerate */ }
r => r?,
} Prevention
- Single-writer discipline: never append from two processes.
- When editing artifacts, renumber the full sequence densely.
- Treat any gap as possible data loss — investigate before repairing.
When it happens
Trigger: Lines reordered by an external process; a duplicated record pasted in; a record deleted manually leaving a gap; another writer numbering from 1 instead of 0.
Common situations: Manual artifact surgery; concurrent appends by two processes; migration scripts that renumber incorrectly.
Related errors
- sub-agent transcript message is missing its index
- sub-agent transcript history shrank from {} to {} messages
- sub-agent transcript artifact is empty
- sub-agent transcript artifact header does not match agent {a
- unknown sub-agent transcript artifact record
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/d11aec37e3bd8ce3.
Report an issue: GitHub.