{"record":{"id":"2cb796285060bfe5","repo":"astrid-runtime/astrid","slug":"distro-lock-capsule-capsule-catalog-entry-has","errorCode":null,"errorMessage":"Distro.lock capsule '{capsule}' catalog entry has no readable bytes: bin/{locked_hex}.wasm","messagePattern":"Distro\\.lock capsule '(.+?)' catalog entry has no readable bytes: bin/(.+?)\\.wasm","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/init_grant.rs","lineNumber":403,"sourceCode":"            .content()\n            .describe(&astrid_storage::StateOwner::System, &name)\n            .map_err(|error| anyhow::anyhow!(error))?\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"Distro.lock capsule '{capsule}' catalog entry is missing: bin/{locked_hex}.wasm\"\n                )\n            })?;\n        store\n            .content()\n            .read_range(\n                &astrid_storage::StateOwner::System,\n                &name,\n                0,\n                descriptor.logical_bytes(),\n            )\n            .map_err(|error| anyhow::anyhow!(error))?\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"Distro.lock capsule '{capsule}' catalog entry has no readable bytes: bin/{locked_hex}.wasm\"\n                )\n            })?\n    } else {\n        let blob_path = home.bin_dir().join(format!(\"{locked_hex}.wasm\"));\n        std::fs::read(&blob_path).with_context(|| {\n            format!(\n                \"Distro.lock capsule '{}' content blob is missing or unreadable at {}\",\n                capsule,\n                blob_path.display()\n            )\n        })?\n    };\n    let actual = blake3::hash(&bytes);\n    if actual != locked {\n        bail!(\"Distro.lock capsule '{capsule}' content blob bytes do not match hash {locked_hash}\");\n    }\n    Ok(())","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/init_grant.rs#L385-L421","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet bytes = store.content().read_range(...)?  // None -> error\n// after\n$ astrid distro sync   // restore readable bytes in backend, then retry grant","handlingStrategy":"validation","validationCode":"fn catalog_bytes_readable(store: &Store, locked_hex: &str) -> bool {\n    let name = astrid_storage::ContentName::new(format!(\"bin/{locked_hex}.wasm\")).unwrap();\n    match store.content().describe(&astrid_storage::StateOwner::System, &name) {\n        Ok(Some(d)) => store.content().read_range(&name, 0, d.logical_bytes()).map(|b| b.is_some()).unwrap_or(false),\n        _ => false,\n    }\n}","typeGuard":null,"tryCatchPattern":"match res {\n    Err(e) if e.to_string().contains(\"no readable bytes\") => repair_backend_or_reingest(),\n    other => other,\n}","preventionTips":["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"],"tags":["cli","distro-lock","storage","wasm"],"backgroundTag":"empty-response-body","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}