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

  1. Propose in the round reported by the latest chain info; let the client's propose flow compute the current round and leader.
  2. For fast blocks, sign with a super-owner key; regular owners must use multi- or single-leader rounds.
  3. If you should be an owner, have a current owner add your key via an ownership-change block.
  4. 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

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


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