linera-io/linera-protocol · error · ChainError

Block proposal has size {0} which is too large

Error message

Block proposal has size {0} which is too large

What it means

ProposedBlock::check_proposal_size (linera-chain/src/data_types/mod.rs:141-148) bcs-serializes the block and rejects it if it exceeds the committee policy's maximum_block_proposal_size — 13,000,000 bytes in the default production policy (linera-execution/src/policy.rs:326), u64::MAX in the test default (policy.rs:241). Both stage_block_execution (linera-core/src/chain_worker/state.rs:2424) and try_handle_block_proposal (state.rs:2529) enforce the limit, so oversized proposals never execute.

Source

Thrown at linera-chain/src/data_types/mod.rs:143

    pub fn operations(&self) -> impl Iterator<Item = &Operation> {
        self.transactions.iter().filter_map(|tx| match tx {
            Transaction::ExecuteOperation(operation) => Some(operation),
            Transaction::ReceiveMessages(_) => None,
        })
    }

    /// Returns all incoming bundles in this block.
    pub fn incoming_bundles(&self) -> impl Iterator<Item = &IncomingBundle> {
        self.transactions.iter().filter_map(|tx| match tx {
            Transaction::ReceiveMessages(bundle) => Some(bundle),
            Transaction::ExecuteOperation(_) => None,
        })
    }

    /// Checks that the serialized size of this block does not exceed the given maximum.
    pub fn check_proposal_size(&self, maximum_block_proposal_size: u64) -> Result<(), ChainError> {
        let size = bcs::serialized_size(self)?;
        ensure!(
            size <= usize::try_from(maximum_block_proposal_size).unwrap_or(usize::MAX),
            ChainError::BlockProposalTooLarge(size)
        );
        Ok(())
    }
}

#[async_graphql::ComplexObject]
impl ProposedBlock {
    /// Metadata about the transactions in this block.
    async fn transaction_metadata(&self) -> Vec<TransactionMetadata> {
        self.transactions
            .iter()
            .map(TransactionMetadata::from_transaction)
            .collect()
    }
}

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Split the block into several smaller proposals at the same or successive heights
  2. Publish large data as blobs through the blob-storage flow first and reference them by BlobId in the block instead of inlining the bytes
  3. If you operate the committee, raise maximum_block_proposal_size in the policy (genesis config or policy update path)

Example fix

// before: inlining a big blob's bytes into the block
let block = ProposedBlock { transactions: vec![Transaction::ExecuteOperation(
    Operation::system(SystemOperation::PublishDataBlob(blob_bytes)),
)], .. };

// after: publish via blob service, reference by id in (smaller) blocks
let blob_id = client.publish_data_blob(blob_bytes).await?; // stored out-of-band
let block = ProposedBlock { transactions: vec![Transaction::ExecuteOperation(
    Operation::system(SystemOperation::PublishBlob { blob_id }),
)], .. };
Defensive patterns

Strategy: validation

Validate before calling

// Cheap pre-submit mirror of check_proposal_size (data_types/mod.rs:141):
let size = bcs::serialized_size(&block)?;
let limit = usize::try_from(policy.maximum_block_proposal_size).unwrap_or(usize::MAX);
if size > limit {
    anyhow::bail!("block proposal is {size} bytes > limit {limit}; split it or use blobs");
}

Try / catch

match result {
    Err(ChainError::BlockProposalTooLarge(size)) => {
        // split the block, or move large payloads to the blob service and reference
        // BlobIds; retrying the identical block cannot succeed
    }
    other => other?,
}

Prevention

When it happens

Trigger: Blocks inlining large published blobs or many big transactions (check_proposal_size counts the whole serialized ProposedBlock); a committee that lowered maximum_block_proposal_size (it is configurable via genesis/policy, linera-service/src/cli/command.rs:317); tests deliberately setting tiny limits (e.g., fee_consumption.rs uses 61 bytes).

Common situations: Publishing large data (images, WASM bytecode, state blobs) inside the block instead of via the blob service; batch jobs packing thousands of operations into one block; a policy change shrinking limits while old batching logic remained.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/193b556ecb3ecb83. Report an issue: GitHub.