linera-io/linera-protocol · critical · ChainClientError
Protocol error within chain client: A quorum confirmed with
Error message
Protocol error within chain client: A quorum confirmed with a justification commitment that does not match the validated certificate's justification chain
What it means
Raised in Client::finalize_block after a confirming quorum forms on a ConfirmedBlock. The client assembles the final certificate from the quorum's votes plus a justification chain (empty iff the quorum attested first_round). If the justification commitment the votes signed does not equal the commitment of the chain the client attaches, the assembled certificate would fail signature verification everywhere, so the client refuses with this ProtocolError instead of broadcasting a broken certificate.
Source
Thrown at linera-core/src/client/mod.rs:1337
certificate: Box::new(certificate),
delivery: self.options.cross_chain_message_delivery,
};
let quorum = self
.communicate_chain_action(committee, finalize_action, hashed_value)
.await?;
// Omit the chain iff the confirming votes attested that this is the chain's first round:
// such a block is always the lower one in any fork, so it never needs a chain of its own.
// Deciding from the quorum's signed attestation — rather than our local ownership view,
// which a concurrently finalized block could have advanced to a different first round —
// guarantees the certificate we assemble matches what the validators actually signed.
let justification = if quorum.first_round() {
JustificationChain::default()
} else {
full_justification
};
// The confirming votes committed to the chain they were shown; the chain we attach must
// be that one, or the assembled certificate would fail verification everywhere.
ensure!(
quorum.justification_commitment() == justification.commitment(quorum.hash()),
chain_client::Error::ProtocolError(
"A quorum confirmed with a justification commitment that does not match the \
validated certificate's justification chain",
)
);
let certificate = ConfirmedBlockCertificate::from_parts(quorum, justification);
self.receive_certificate_with_checked_signatures(
certificate.clone(),
ProcessConfirmedBlockMode::Execute,
)
.await?;
Ok(certificate)
}
/// Submits a block proposal to the validators.
#[instrument(level = "trace", skip_all)]
async fn submit_block_proposal<T: ProcessableCertificate>(View on GitHub (pinned to 6c226ddcb3)
Solutions
- Retry the operation: discard the pending block, re-prepare the chain (prepare_chain synchronizes from validators) and let process_pending_block rebuild and finalize
- Make sure only one client instance proposes/finalizes on a given chain at a time (single owner per chain)
- Check that all validators run the same (latest) linera version
- If reproducible, capture the certificates and votes and report it as a protocol bug
Defensive patterns
Strategy: retry
Type guard
fn is_justification_commitment_mismatch(err: &chain_client::Error) -> bool {
matches!(
err,
chain_client::Error::ProtocolError(
"A quorum confirmed with a justification commitment that does not match the \
validated certificate's justification chain"
)
)
} Try / catch
match client.process_pending_block().await {
Err(e) if is_justification_commitment_mismatch(&e) => {
// Quorum signed a different justification chain; re-sync and retry once.
client.prepare_chain().await?;
client.process_pending_block().await
}
other => other,
} Prevention
- Run exactly one active client per owner chain; concurrent finalizers produce exactly this race
- Keep the whole committee on the same linera-protocol version
- Log quorum attestation fields (first_round, justification_commitment) when the error fires — a pattern across rounds indicates a faulty validator
When it happens
Trigger: A quorum of validators signed confirm votes over a justification chain derived from a different (competing) validated certificate than the one this client holds; concurrent finalization attempts on the same chain/height; byzantine validators returning votes fabricated over another chain; fork/race during process_pending_block.
Common situations: Two clients (or a retried client and a stale one) driving the same chain simultaneously; validators recovering from a restart with stale locking state; mixed validator versions after a protocol upgrade. Persistent occurrence on a healthy network indicates a real protocol bug or a faulty validator.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Protocol error within chain client: A quorum voted with a ju
- Certificate justification commitment does not match its just
- Certificate unlocking round does not match the top of its ju
- Justification chain must lie in rounds strictly below the ce
- Certificate carries the first-round attestation but was not
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/5b9ece7e6b40a579.
Report an issue: GitHub.