linera-io/linera-protocol · error · WorkerError
BlobsNotFound
BlobsNotFound
Error message
Blobs not found: {0:?} What it means
A block references blobs by ID (contract bytecode, committee blobs, data blobs it reads or publishes). get_required_blobs looks in the block's own created blobs, the manager's pending blobs, and storage; any ID found nowhere is returned in this error, aborting proposal or certificate processing.
Source
Thrown at linera-core/src/chain_worker/state.rs:462
.await?
.ok_or(WorkerError::BlobsNotFound(vec![blob_id]))
}
/// Reads the blobs from the chain manager or from storage. Returns an error if any are
/// missing.
#[instrument(skip_all, fields(
chain_id = %self.chain_id()
))]
async fn get_required_blobs(
&self,
required_blob_ids: impl IntoIterator<Item = BlobId>,
created_blobs: BTreeMap<BlobId, Blob>,
) -> Result<BTreeMap<BlobId, Blob>, WorkerError> {
let maybe_blobs = self
.maybe_get_required_blobs(required_blob_ids, Some(created_blobs))
.await?;
let not_found_blob_ids = missing_blob_ids(&maybe_blobs);
ensure!(
not_found_blob_ids.is_empty(),
WorkerError::BlobsNotFound(not_found_blob_ids)
);
Ok(maybe_blobs
.into_iter()
.filter_map(|(blob_id, maybe_blob)| Some((blob_id, maybe_blob?)))
.collect())
}
/// Tries to read the blobs from the chain manager or storage. Returns `None` if not found.
#[instrument(skip_all, fields(
chain_id = %self.chain_id()
))]
async fn maybe_get_required_blobs(
&self,
blob_ids: impl IntoIterator<Item = BlobId>,
mut created_blobs: Option<BTreeMap<BlobId, Blob>>,
) -> Result<BTreeMap<BlobId, Option<Blob>>, WorkerError> {View on GitHub (pinned to 6c226ddcb3)
Solutions
- Upload the missing blobs (the error lists the exact BlobIds) via the blob endpoint / publish_blob, then retry the proposal or certificate
- When proposing, publish blob content before or together with the block so validators can fetch or receive it
- Ensure blob propagation/gossip is configured so validators request missing blobs from peers instead of failing
Example fix
// before: block references blobs the validator does not have
client.submit_proposal(proposal).await?; // BlobsNotFound([...])
// after: upload each listed blob, then retry the same proposal
for blob_id in missing_blob_ids {
let blob = local_blob_store.read(blob_id)?; // or fetch from another node
client.publish_blob(chain_id, blob).await?;
}
client.submit_proposal(proposal).await?; Defensive patterns
Strategy: retry
Validate before calling
// Pre-upload blobs the block depends on, so the proposal is never rejected.
for blob_id in block.required_blob_ids() {
if client.read_blob(blob_id).await?.is_none() {
let blob = local_store.read(blob_id)?; // or fetch from a peer
client.publish_blob(chain_id, blob).await?;
}
}
client.submit_proposal(proposal).await?; Type guard
fn blobs_not_found(e: &WorkerError) -> Option<&Vec<BlobId>> {
match e {
WorkerError::BlobsNotFound(ids) => Some(ids),
_ => None,
}
} Try / catch
match client.submit_proposal(proposal).await {
Err(e) if matches!(e, ref x if x.blobs_not_found().is_some()) => {
for blob_id in e.blobs_not_found().unwrap() {
let blob = local_store.read(blob_id)?; // or fetch from peers
client.publish_blob(chain_id, blob).await?;
}
client.submit_proposal(proposal).await?; // retry unchanged
}
other => other?,
} Prevention
- Publish blob content to validators before or together with blocks that reference it
- Keep blob propagation (gossip) enabled so validators backfill missing blobs automatically
- Configure blob retention/GC so still-referenced blobs are never pruned
When it happens
Trigger: try_handle_block_proposal or process_confirmed_block for a block whose required_blob_ids are unknown to this validator. For proposals, load_proposal_blobs first registers the missing IDs as pending blobs and expects the client to upload each blob and retry.
Common situations: Publishing a block that reads or publishes blobs without uploading blob content to the validators first; a validator that never received the blob via gossip; blob pruning/GC removing a still-referenced blob; new node syncing without blob backfill.
Related errors
- MetaMask is not available
- Failed to parse {spawn_mode_name} as a spawn_mode
- Failed to find address for {s}. {parse_error}
- Failed to find port for {s}. {parse_error}
- Failed to find parse port {port_str} for {s}. {parse_error}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/79f0174e7f48d2d9.
Report an issue: GitHub.