astrid-runtime/astrid · critical
unexpected {kind:?} in a canonical File owning closure
Error message
unexpected {kind:?} in a canonical File owning closure What it means
During construction of a canonical File sketch, `collect_chunks` recursively walks the content DAG from a File record, flattening its owning closure into an ordered chunk list. It only expects to encounter `Chunk` records (leaf data) and `File`/`ChunkTree` records (interior nodes); any other ObjectKind reached through owning references means the DAG contains an object type that cannot legally appear inside a File's owning closure, so the walk aborts rather than silently mis-flatten it.
Source
Thrown at crates/astrid-storage-chunker-evidence/src/sketch.rs:482
.get(&id)
.copied()
.ok_or_else(|| anyhow::anyhow!("content DAG misses {id:?}"))?;
match record.kind() {
ObjectKind::Chunk => {
let length = u64::try_from(record.canonical_bytes().len())?;
chunks.push(Chunk {
id,
offset: *offset,
length,
});
*offset = checked_add(*offset, length, "chunk offset")?;
},
ObjectKind::File | ObjectKind::ChunkTree => {
for child in record.owning_references() {
collect_chunks(child, records, offset, chunks)?;
}
},
kind => bail!("unexpected {kind:?} in a canonical File owning closure"),
}
Ok(())
}
fn best_resemblance_candidate(
corpus_kind: CorpusKind,
sketches: &[Option<MaterializedSketch>],
versions: &[Version],
inverted: &BTreeMap<[u8; 32], Vec<usize>>,
target: usize,
sample_size: u16,
) -> Option<usize> {
let mut best: Option<(usize, u64, u64)> = None;
let target_sketch = sketches.get(target)?.as_ref()?;
let candidates = target_sketch
.scores
.iter()
.filter_map(|score| inverted.get(score))View on GitHub (pinned to affd8760f4)
Solutions
- Inspect the offending ObjectId's ObjectRecord and fix the producer that linked it into a File's owning_references — only Chunk and File/ChunkTree nodes belong there.
- Verify the record map passed to the sketch builder is complete and from the intended corpus version; reload or rebuild the evidence store if it was migrated.
- If a new ObjectKind is legitimately part of File closures, extend collect_chunks's match to handle it explicitly instead of falling into the bail arm.
- Run a DAG validation pass over the object store (every owning_reference resolves to Chunk/File/ChunkTree) before sketching.
Example fix
// before
kind => bail!("unexpected {kind:?} in a canonical File owning closure"),
// after
ObjectKind::Blob => { /* handle the newly supported kind */ },
kind => bail!("unexpected {kind:?} in a canonical File owning closure"), Defensive patterns
Strategy: validation
Validate before calling
fn validate_file_closure(records: &BTreeMap<ObjectId, &ObjectRecord>, id: ObjectId) -> Result<()> {
let mut stack = vec![id];
while let Some(id) = stack.pop() {
let record = records.get(&id).ok_or_else(|| anyhow::anyhow!("missing {id:?}"))?;
match record.kind() {
ObjectKind::Chunk => {},
ObjectKind::File | ObjectKind::ChunkTree => stack.extend(record.owning_references()),
other => bail!("illegal {other:?} in File closure at {id:?}"),
}
}
Ok(())
} Type guard
fn is_legal_closure_kind(kind: ObjectKind) -> bool {
matches!(kind, ObjectKind::Chunk | ObjectKind::File | ObjectKind::ChunkTree)
} Try / catch
match collect_chunks(root, &records, &mut off, &mut chunks) {
Err(e) if e.to_string().contains("in a canonical File owning closure") => {
log::error!("store corrupt: non-chunk object linked under a File; rebuild store");
},
Err(e) => return Err(e),
Ok(()) => {},
} Prevention
- Validate the content DAG (kinds of all owning_references) before sketching.
- Only allow the writer API to link Chunk/File/ChunkTree nodes as owning children of Files.
- Reject unknown ObjectKind values at store ingestion time.
When it happens
Trigger: Calling sketch construction (e.g. `from_built` or another `collect_chunks` entry point) over a content-DAG record map where a File/ChunkTree's `owning_references()` chain includes an object whose `kind()` is neither Chunk, File, nor ChunkTree — e.g. a manifest/metadata-style object accidentally linked as an owning child of a File.
Common situations: A storage writer bug or corrupted evidence store links a non-chunk object (e.g. a corpus index record or a newer object kind introduced by a version change) under a File node; hand-edited or migrated object stores referencing records with unexpected kinds.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- equal chunk identities named different bytes in delta eviden
- encoded evidence delta did not reconstruct its target
- durable capsule {id} disappeared after publish
- durable capsule {id} failed authoritative verification
- publish WASM into the system content catalog
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f1b62cd23e2f91ee.
Report an issue: GitHub.