linera-io/linera-protocol · error · ExecutionError

AdminOperationOnNonAdminChain

AdminOperationOnNonAdminChain

Error message

ExecutionError::AdminOperationOnNonAdminChain

What it means

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.

Source

Thrown at linera-execution/src/system.rs:503

                owner,
                target_id,
                recipient,
                amount,
            } => {
                let maybe_message = self
                    .claim(
                        context.authenticated_owner,
                        None,
                        owner,
                        target_id,
                        recipient,
                        amount,
                    )
                    .await?;
                txn_tracker.add_outgoing_messages(maybe_message);
            }
            Admin(admin_operation) => {
                ensure!(
                    *self.admin_chain_id.get() == Some(context.chain_id),
                    ExecutionError::AdminOperationOnNonAdminChain
                );
                match admin_operation {
                    AdminOperation::PublishCommitteeBlob { blob_hash } => {
                        self.blob_published(
                            &BlobId::new(blob_hash, BlobType::Committee),
                            txn_tracker,
                        )?;
                    }
                    AdminOperation::CreateCommittee { epoch, blob_hash } => {
                        self.check_next_epoch(epoch)?;
                        let blob_id = BlobId::new(blob_hash, BlobType::Committee);
                        // Validate that the blob exists and deserializes as a Committee.
                        self.context()
                            .extra()
                            .get_or_load_committee_by_hash(blob_hash)
                            .await?;

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. 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.
  2. Verify wallet and endpoint refer to the same network (chain IDs are network-specific); re-import or regenerate the wallet for the target network.
  3. 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.

Example fix

// before: admin op sent from a user chain
let op = Operation::system(SystemOperation::Admin(AdminOperation::RemoveCommittee { epoch }));
client.process_operations(user_chain_id, vec![op]).await?; // AdminOperationOnNonAdminChain

// after: same op from the admin chain recorded in genesis
client.process_operations(admin_chain_id, vec![op]).await?;
Defensive patterns

Strategy: validation

Validate before calling

// before submitting admin ops, compare with the network's admin chain
let admin_chain_id = genesis.admin_chain_id; // from the genesis config
if Some(executing_chain_id) != Some(admin_chain_id) {
    return Err(format!("admin ops must run on {}", admin_chain_id));
}

Try / catch

match result {
    Err(ExecutionError::AdminOperationOnNonAdminChain) => {
        // wrong chain: do not retry here; resubmit from the genesis admin chain
    }
    other => other,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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