linera-io/linera-protocol · error · WorkerError
InvalidOwner
InvalidOwner
Error message
Block was not signed by an authorized owner
What it means
Every block proposal is checked with ChainManager::can_propose: super owners may propose in any round except validator rounds; Round::Fast accepts super owners only; SingleLeader and Validator rounds accept only the computed round leader; MultiLeader rounds accept any owner, or anyone if the chain set open_multi_leader_rounds. InvalidOwner means the signing owner is not permitted to propose in the proposal's round.
Source
Thrown at linera-core/src/chain_worker/state.rs:2531
.map_err(|msg| WorkerError::InvalidBlockProposal(msg.to_string()))?;
proposal.check_signature()?;
let owner = proposal.owner();
let BlockProposal {
content,
original_proposal,
signature: _,
} = &proposal;
let block = &content.block;
let chain = &self.chain;
// Check if the chain is ready for this new block proposal.
chain.tip_state.get().verify_block_chaining(block)?;
// Check the epoch.
let (epoch, committee) = chain.current_committee().await?;
check_block_epoch(epoch, block.chain_id, block.epoch)?;
let policy = committee.policy().clone();
block.check_proposal_size(policy.maximum_block_proposal_size)?;
// Check the authentication of the block.
ensure!(
chain.manager.can_propose(&owner, proposal.content.round),
WorkerError::InvalidOwner
);
let old_round = self.chain.manager.current_round();
match original_proposal {
None => {
if let Some(signer) = block.authenticated_owner {
// Check the authentication of the operations in the new block.
ensure!(signer == owner, WorkerError::InvalidSigner(owner));
}
}
Some(OriginalProposal::Regular { certificate }) => {
// Verify that this block has been validated by a quorum before.
certificate.check(&committee)?;
}
Some(OriginalProposal::Fast(signature)) => {
let original_proposal = BlockProposal {
content: ProposalContent {View on GitHub (pinned to 6c226ddcb3)
Solutions
- Propose in the round reported by the latest chain info; let the client's propose flow compute the current round and leader.
- For fast blocks, sign with a super-owner key; regular owners must use multi- or single-leader rounds.
- If you should be an owner, have a current owner add your key via an ownership-change block.
- If any owner may propose in multi-leader rounds, set open_multi_leader_rounds in the chain's ownership.
Example fix
// before: regular owner forcing a fast round
let round = Round::Fast;
// after: pick a round this owner may propose in
let round = if ownership.super_owners.contains(&my_owner) {
Round::Fast
} else {
ownership.first_round() // MultiLeader(0) or SingleLeader(0)
}; Defensive patterns
Strategy: validation
Validate before calling
// Mirror of ChainManager::can_propose before submitting.
fn can_propose(ownership: &ChainOwnership, owner: &AccountOwner, round: Round) -> bool {
if ownership.super_owners.contains(owner) {
return !round.is_validator();
}
match round {
Round::Fast => false,
Round::MultiLeader(_) => ownership.can_propose_in_multi_leader_round(owner),
Round::SingleLeader(_) | Round::Validator(_) => false, // leader check is validator-side
}
} Try / catch
match node.handle_block_proposal(proposal).await {
Err(NodeError::WorkerError(err)) if matches!(*err, WorkerError::InvalidOwner) => {
// Refresh chain info, recompute the allowed round, and re-sign with an authorized key.
}
result => result,
} Prevention
- Always derive the proposal round from fresh chain info rather than fixing it in code.
- Keep the proposing key in the chain's current ChainOwnership.
- Fast rounds are super-owner only: check super_owners before choosing Round::Fast.
- After ownership changes, refresh the client before proposing.
When it happens
Trigger: Proposing in Round::Fast with a regular owner key; proposing in SingleLeader(n) or Validator(n) when the leader computation picks a different owner; proposing in MultiLeader rounds without being an owner on a chain with open_multi_leader_rounds=false; signing with a key that is not in ChainOwnership at all.
Common situations: Wallet configured with the wrong key for the chain; proposing at a stale round after timeouts moved leadership; ownership changed by another owner so your key was removed; private chains that did not open multi-leader rounds.
Related errors
- InvalidSigner
- CannotRejectMessage
- InvalidBlockChaining
- FalseFirstRoundAttestation
- Fast blocks cannot query oracles
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/d27544b9f6f451cb.
Report an issue: GitHub.