astrid-runtime/astrid · error
Distro.lock capsule '{capsule}' catalog entry has no readabl
Error message
Distro.lock capsule '{capsule}' catalog entry has no readable bytes: bin/{locked_hex}.wasm What it means
After the catalog descriptor exists, `read_range` is expected to return the WASM bytes; when it returns None the catalog entry has no readable bytes. The library needs the bytes to hash-verify the locked WASM, so a descriptor without readable content is treated as a corrupt or inconsistent catalog entry.
Source
Thrown at crates/astrid-cli/src/commands/init_grant.rs:403
.content()
.describe(&astrid_storage::StateOwner::System, &name)
.map_err(|error| anyhow::anyhow!(error))?
.ok_or_else(|| {
anyhow::anyhow!(
"Distro.lock capsule '{capsule}' catalog entry is missing: bin/{locked_hex}.wasm"
)
})?;
store
.content()
.read_range(
&astrid_storage::StateOwner::System,
&name,
0,
descriptor.logical_bytes(),
)
.map_err(|error| anyhow::anyhow!(error))?
.ok_or_else(|| {
anyhow::anyhow!(
"Distro.lock capsule '{capsule}' catalog entry has no readable bytes: bin/{locked_hex}.wasm"
)
})?
} else {
let blob_path = home.bin_dir().join(format!("{locked_hex}.wasm"));
std::fs::read(&blob_path).with_context(|| {
format!(
"Distro.lock capsule '{}' content blob is missing or unreadable at {}",
capsule,
blob_path.display()
)
})?
};
let actual = blake3::hash(&bytes);
if actual != locked {
bail!("Distro.lock capsule '{capsule}' content blob bytes do not match hash {locked_hash}");
}
Ok(())View on GitHub (pinned to affd8760f4)
Solutions
- Re-ingest the WASM content so the backend holds its bytes (re-run publish/sync for the capsule)
- Repair the storage backend (restore blob data) or point the config at the correct data directory
- Delete the stale catalog entry and re-add the content
- Regenerate the lock and re-sync the distro if the stored content no longer matches
Example fix
// before let bytes = store.content().read_range(...)? // None -> error // after $ astrid distro sync // restore readable bytes in backend, then retry grant
Defensive patterns
Strategy: validation
Validate before calling
fn catalog_bytes_readable(store: &Store, locked_hex: &str) -> bool {
let name = astrid_storage::ContentName::new(format!("bin/{locked_hex}.wasm")).unwrap();
match store.content().describe(&astrid_storage::StateOwner::System, &name) {
Ok(Some(d)) => store.content().read_range(&name, 0, d.logical_bytes()).map(|b| b.is_some()).unwrap_or(false),
_ => false,
}
} Try / catch
match res {
Err(e) if e.to_string().contains("no readable bytes") => repair_backend_or_reingest(),
other => other,
} Prevention
- Monitor storage backend health (index/data consistency)
- Restore blobs after disk cleanups before validating locks
- Re-ingest content after any partial ingest failure
- Verify descriptor logical_bytes against actual stored size
When it happens
Trigger: `validate_locked_wasm` calls `store.content().read_range(&name, 0, descriptor.logical_bytes())`; the result maps to None, raising this error. This is the non-blob fallback path (store-backed content), meaning describe succeeded but the payload is missing/unreadable in the content backend.
Common situations: Catalog index intact but backing blob storage lost (e.g. disk cleanup, partial deletion); backend desync between index and data store; logical_bytes reported but payload truncated or missing after a failed ingest.
Related errors
- Distro.lock capsule '{capsule}' catalog entry is missing: bi
- durable capsule {id} WASM hash differs between metadata and
- durable capsule {id} metadata names a hash for a non-WASM co
- durable capsule {id} metadata names a component absent from
- Distro.lock capsule '{capsule}' content blob bytes do not ma
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/2cb796285060bfe5.
Report an issue: GitHub.