{"record":{"id":"5d6373aecf684167","repo":"linera-io/linera-protocol","slug":"adminoperationonnonadminchain","errorCode":"AdminOperationOnNonAdminChain","errorMessage":"ExecutionError::AdminOperationOnNonAdminChain","messagePattern":"ExecutionError::AdminOperationOnNonAdminChain","errorType":"exception","errorClass":"ExecutionError","httpStatus":null,"severity":"error","filePath":"linera-execution/src/system.rs","lineNumber":503,"sourceCode":"                owner,\n                target_id,\n                recipient,\n                amount,\n            } => {\n                let maybe_message = self\n                    .claim(\n                        context.authenticated_owner,\n                        None,\n                        owner,\n                        target_id,\n                        recipient,\n                        amount,\n                    )\n                    .await?;\n                txn_tracker.add_outgoing_messages(maybe_message);\n            }\n            Admin(admin_operation) => {\n                ensure!(\n                    *self.admin_chain_id.get() == Some(context.chain_id),\n                    ExecutionError::AdminOperationOnNonAdminChain\n                );\n                match admin_operation {\n                    AdminOperation::PublishCommitteeBlob { blob_hash } => {\n                        self.blob_published(\n                            &BlobId::new(blob_hash, BlobType::Committee),\n                            txn_tracker,\n                        )?;\n                    }\n                    AdminOperation::CreateCommittee { epoch, blob_hash } => {\n                        self.check_next_epoch(epoch)?;\n                        let blob_id = BlobId::new(blob_hash, BlobType::Committee);\n                        // Validate that the blob exists and deserializes as a Committee.\n                        self.context()\n                            .extra()\n                            .get_or_load_committee_by_hash(blob_hash)\n                            .await?;","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-execution/src/system.rs#L485-L521","documentation":"Linera reserves a set of Admin operations (PublishCommitteeBlob, CreateCommittee, RemoveCommittee) for the network's admin chain. Every chain stores the admin_chain_id assigned at genesis, and execute_operation (system.rs:503) only accepts SystemOperation::Admin when the executing chain is exactly that chain. Any other chain (or an uninitialized chain where admin_chain_id is None) fails with AdminOperationOnNonAdminChain and the block is rejected.","triggerScenarios":"Submitting a block containing SystemOperation::Admin(...) from a chain that is not the network's admin chain: using the wrong chain from the wallet, running admin tooling against a user chain, or pointing a client at a different network than the wallet/gensis expects.","commonSituations":"Local dev with a freshly generated network while scripts still reference an old admin chain; wallets holding several chains and the operator picking the wrong one; mixing testnet and devnet configs; automated committee-rotation jobs configured with a stale chain ID after the network was regenerated.","solutions":["Find the admin chain ID in the network's genesis configuration / wallet (it is the chain that created the network) and submit the Admin operation from that chain.","Verify wallet and endpoint refer to the same network (chain IDs are network-specific); re-import or regenerate the wallet for the target network.","If the admin chain's key is not in your wallet, obtain it (or ask the network operator to run the admin operation) rather than retrying from another chain."],"exampleFix":"// before: admin op sent from a user chain\nlet op = Operation::system(SystemOperation::Admin(AdminOperation::RemoveCommittee { epoch }));\nclient.process_operations(user_chain_id, vec![op]).await?; // AdminOperationOnNonAdminChain\n\n// after: same op from the admin chain recorded in genesis\nclient.process_operations(admin_chain_id, vec![op]).await?;","handlingStrategy":"validation","validationCode":"// before submitting admin ops, compare with the network's admin chain\nlet admin_chain_id = genesis.admin_chain_id; // from the genesis config\nif Some(executing_chain_id) != Some(admin_chain_id) {\n    return Err(format!(\"admin ops must run on {}\", admin_chain_id));\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(ExecutionError::AdminOperationOnNonAdminChain) => {\n        // wrong chain: do not retry here; resubmit from the genesis admin chain\n    }\n    other => other,\n}","preventionTips":["Pin the admin chain ID (and the matching wallet key) in committee-rotation scripts instead of 'first chain in wallet'.","When regenerating a local network, update every script that references the old admin chain.","Verify wallet, endpoint, and genesis belong to the same network before admin operations."],"tags":["linera","admin-chain","committee","permissions","blockchain","configuration"],"backgroundTag":"admin-operation-permission-denied","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}