linera-io/linera-protocol · error · Error

Invalid owner address

Error message

Invalid owner address

What it means

WalletSynchronizationError in pending_message_bundles fires when a chain has only super owners (no regular owners). Super-owner chains have no automatic leader, so nobody regularly proposes blocks; the client therefore requires that the local node is at least as advanced as the wallet's trusted state (initial_next_block_height). If the local node is behind the certificates the wallet already trusts, querying pending messages would return an incomplete view, so the client refuses and asks you to synchronize with validators.

Source

Thrown at web/@linera/client/src/signer/PrivateKey.ts:45

    return PrivateKey.fromMnemonic(mnemonic);
  }

  static fromMnemonic(mnemonic: string): PrivateKey {
    const wallet = ethers.Wallet.fromPhrase(mnemonic);
    return new PrivateKey(wallet.privateKey);
  }

  public address(): string {
    return this.wallet.address;
  }

  async sign(owner: string, value: Uint8Array): Promise<string> {
    if (
      typeof owner !== "string" ||
      !ethers.isAddress(owner) ||
      this.wallet.address.toLowerCase() !== owner.toLowerCase()
    ) {
      throw new Error("Invalid owner address");
    }
    // ethers expects a string or Bytes for EIP-191
    const signature = await this.wallet.signMessage(value);

    return signature;
  }

  async getPublicKey(owner: string): Promise<string> {
    if (
      typeof owner !== "string" ||
      !ethers.isAddress(owner) ||
      this.wallet.address.toLowerCase() !== owner.toLowerCase()
    ) {
      throw new Error("Invalid owner address");
    }
    return this.wallet.signingKey.publicKey;
  }

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Call client.synchronize_from_validators() (or synchronize_up_to(initial_next_block_height)) on this chain before reading pending messages or balances.
  2. Run the wallet/service against a validator that actually has the missing certificates (check the --wallet with-grpc* / validator endpoints config).
  3. As a super owner, periodically propose a block (e.g. via `linera process-inbox` / retry-pending-block) so the chain advances and the invariant stays easy to maintain.
  4. If you never need this guard, add a regular owner to the chain so automatic synchronization applies.

Example fix

// before: reading pending messages on a super-owner chain with a stale local node
let bundles = client.pending_message_bundles().await?; // WalletSynchronizationError

// after: sync the trusted state into the local node first
client.synchronize_from_validators().await?;
let bundles = client.pending_message_bundles().await?;
Defensive patterns

Strategy: retry

Validate before calling

// For super-owner chains, ensure the node caught up before reading pending data
let info = client.chain_info().await?;
if info.next_block_height < client.initial_next_block_height() {
    client.synchronize_from_validators().await?;
}

Try / catch

match client.pending_message_bundles().await {
    Ok(bundles) => bundles,
    Err(Error::WalletSynchronizationError) => {
        client.synchronize_from_validators().await?;
        client.pending_message_bundles().await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling pending_message_bundles (directly or via prepend_epochs_messages_and_events, query_balances_with_owner) on a chain whose ownership.is_super_owner_no_regular_owners(owner) is true, while info.next_block_height < self.initial_next_block_height. Producers: reading messages/balances on a super-owner chain right after wallet load, or after the wallet received certificates (e.g. via a faucet or another node) that the local node has not processed.

Common situations: Super-owner (manually operated) chains used for benchmarks or scheduled operations; restarting a wallet against a fresh local node/validator; moving a wallet file between environments where the new node lacks the trusted blocks.

Related errors


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