{"record":{"id":"d27544b9f6f451cb","repo":"linera-io/linera-protocol","slug":"invalidowner","errorCode":"InvalidOwner","errorMessage":"Block was not signed by an authorized owner","messagePattern":"Block was not signed by an authorized owner","errorType":"validation","errorClass":"WorkerError","httpStatus":null,"severity":"error","filePath":"linera-core/src/chain_worker/state.rs","lineNumber":2531,"sourceCode":"            .map_err(|msg| WorkerError::InvalidBlockProposal(msg.to_string()))?;\n        proposal.check_signature()?;\n        let owner = proposal.owner();\n        let BlockProposal {\n            content,\n            original_proposal,\n            signature: _,\n        } = &proposal;\n        let block = &content.block;\n        let chain = &self.chain;\n        // Check if the chain is ready for this new block proposal.\n        chain.tip_state.get().verify_block_chaining(block)?;\n        // Check the epoch.\n        let (epoch, committee) = chain.current_committee().await?;\n        check_block_epoch(epoch, block.chain_id, block.epoch)?;\n        let policy = committee.policy().clone();\n        block.check_proposal_size(policy.maximum_block_proposal_size)?;\n        // Check the authentication of the block.\n        ensure!(\n            chain.manager.can_propose(&owner, proposal.content.round),\n            WorkerError::InvalidOwner\n        );\n        let old_round = self.chain.manager.current_round();\n        match original_proposal {\n            None => {\n                if let Some(signer) = block.authenticated_owner {\n                    // Check the authentication of the operations in the new block.\n                    ensure!(signer == owner, WorkerError::InvalidSigner(owner));\n                }\n            }\n            Some(OriginalProposal::Regular { certificate }) => {\n                // Verify that this block has been validated by a quorum before.\n                certificate.check(&committee)?;\n            }\n            Some(OriginalProposal::Fast(signature)) => {\n                let original_proposal = BlockProposal {\n                    content: ProposalContent {","sourceCodeStart":2513,"sourceCodeEnd":2549,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-core/src/chain_worker/state.rs#L2513-L2549","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: regular owner forcing a fast round\nlet round = Round::Fast;\n\n// after: pick a round this owner may propose in\nlet round = if ownership.super_owners.contains(&my_owner) {\n    Round::Fast\n} else {\n    ownership.first_round() // MultiLeader(0) or SingleLeader(0)\n};","handlingStrategy":"validation","validationCode":"// Mirror of ChainManager::can_propose before submitting.\nfn can_propose(ownership: &ChainOwnership, owner: &AccountOwner, round: Round) -> bool {\n    if ownership.super_owners.contains(owner) {\n        return !round.is_validator();\n    }\n    match round {\n        Round::Fast => false,\n        Round::MultiLeader(_) => ownership.can_propose_in_multi_leader_round(owner),\n        Round::SingleLeader(_) | Round::Validator(_) => false, // leader check is validator-side\n    }\n}","typeGuard":null,"tryCatchPattern":"match node.handle_block_proposal(proposal).await {\n    Err(NodeError::WorkerError(err)) if matches!(*err, WorkerError::InvalidOwner) => {\n        // Refresh chain info, recompute the allowed round, and re-sign with an authorized key.\n    }\n    result => result,\n}","preventionTips":["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."],"tags":["rust","linera","blockchain","consensus","authorization","ownership"],"backgroundTag":"unauthorized-block-proposer","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}