linera-io/linera-protocol · error

keystore does not contain a key for owner {chain_owner}

Error message

keystore does not contain a key for owner {chain_owner}

What it means

The relayer loaded the keystore but it holds no private key for the configured bridge chain owner. After syncing the admin chain, run() verifies signer.contains_key(&chain_owner) because every bridge block on the relayed chain must be signed with that owner's key; the check fails closed at startup instead of failing per block later.

Source

Thrown at linera-bridge/src/relay/mod.rs:177

        wallet,
        signer.clone(),
        &Default::default(),
        None,
        genesis_config,
        linera_core::worker::DEFAULT_BLOCK_CACHE_SIZE,
        linera_core::worker::DEFAULT_EXECUTION_STATE_CACHE_SIZE,
    ))
    .await?;

    // ── Sync admin chain ──
    tracing::info!(%admin_chain_id, "Syncing admin chain from validators...");
    let admin_client = ctx.make_chain_client(admin_chain_id).await?;
    admin_client.synchronize_from_validators().await?;
    let admin_chain_height = admin_client.chain_info().await?.next_block_height;
    tracing::info!(%admin_chain_height, "Admin chain synced");

    // ── Register bridge chain in the local wallet ──
    anyhow::ensure!(
        signer
            .contains_key(&chain_owner)
            .await
            .context("failed to query keystore")?,
        "keystore does not contain a key for owner {chain_owner}"
    );

    ctx.update_wallet_for_new_chain(
        chain_id,
        Some(chain_owner),
        linera_base::data_types::Timestamp::default(),
        linera_base::data_types::Epoch::ZERO,
    )
    .await?;

    ctx.client
        .extend_chain_mode(chain_id, linera_core::client::ListeningMode::FullChain);

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Print the owner the relayer expects (it appears in the error and in the "bridge chain" config) and compare it with the owners in keystore.json.
  2. Import or generate the owner's key into the keystore used at startup (keygen + add to keystore.json, or copy the matching keystore from the setup machine).
  3. If the key is genuinely lost, re-register the bridge chain with a new owner that this keystore controls and update the relayer config.
  4. Verify you passed --keystore pointing at the same keystore used during bridge setup.

Example fix

# before: keystore.json has no entry for the configured chain owner
linera-bridge-relay run --keystore /etc/linera/keystore.json --chain-owner <owner>

# after: generate/import the owner key into that keystore first
linera keygen   # (or paste the owner's secret key into keystore.json)
linera-bridge-relay run --keystore /etc/linera/keystore.json --chain-owner <owner>
Defensive patterns

Strategy: validation

Validate before calling

let keystore = linera_wallet_json::Keystore::read(&keystore_path)?;
let owner: AccountOwner = bridge_config.chain_owner;
ensure!(
    keystore.contains_key(&owner).await?,
    "owner {owner} missing from keystore — import the key before starting"
);

Prevention

When it happens

Trigger: chain_owner (from the bridge configuration) does not match any AccountOwner in keystore.json: keystore generated for a different owner, owner key never imported, or a bridge config created against another machine's keystore.

Common situations: Copying bridge config files between machines without copying keystore.json; regenerating the chain owner key during setup; mixing testnet/mainnet keystores; typos when passing the owner argument.

Related errors


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