linera-io/linera-protocol · error
nonexistent chain `{chain_id}`
Error message
nonexistent chain `{chain_id}` What it means
WalletState::forget_keys calls mutate(chain_id, ...), which returns None when the chain_id key is absent from the wallet's chain map. The outer ok_or_else converts that None into this anyhow error, meaning the wallet file has no entry for the given ChainId at all.
Source
Thrown at linera-wallet-json/src/wallet.rs:199
}
/// Applies a mutation to the chain with the given ID, saving afterwards. Returns `None`
/// if the chain is not in the wallet.
pub fn mutate<R>(
&self,
chain_id: ChainId,
mutate: impl Fn(&mut Chain) -> R,
) -> Option<Result<R, persistent::file::Error>> {
self.0
.chains
.mutate(chain_id, mutate)
.map(|outcome| self.0.save().map(|()| outcome))
}
/// Removes and returns the owner of the given chain, erroring if the chain or owner is absent.
pub fn forget_keys(&self, chain_id: ChainId) -> anyhow::Result<AccountOwner> {
self.mutate(chain_id, |chain| chain.owner.take())
.ok_or_else(|| anyhow::anyhow!("nonexistent chain `{chain_id}`"))??
.ok_or_else(|| anyhow::anyhow!("keypair not found for chain `{chain_id}`"))
}
/// Writes the wallet to its file.
pub fn save(&self) -> Result<(), persistent::file::Error> {
self.0.save()
}
/// Returns the number of chains in the wallet.
pub fn num_chains(&self) -> usize {
self.0.chains.items().len()
}
/// Returns the IDs of all chains in the wallet.
pub fn chain_ids(&self) -> Vec<ChainId> {
self.0.chains.chain_ids()
}
View on GitHub (pinned to 6c226ddcb3)
Solutions
- List the chains actually present: linera wallet show (or wallet.chain_ids()) and confirm the target ID
- Verify you are using the right wallet file: check --wallet path / LINERA_WALLET and the chain's network (devnet vs testnet)
- Re-add the chain before forgetting (linera wallet add-chain ...) if keys were removed earlier
- Double-check the full ChainId string for typos or missing characters
Example fix
// before
let owner = wallet.forget_keys(chain_id)?; // chain never added -> error
// after
if !wallet.chain_ids().contains(&chain_id) {
anyhow::bail!("chain {chain_id} not in this wallet; available: {:?}", wallet.chain_ids());
}
let owner = wallet.forget_keys(chain_id)?; Defensive patterns
Strategy: validation
Validate before calling
// Check membership before mutating
let ids = wallet.chain_ids();
if !ids.contains(&chain_id) {
anyhow::bail!("chain {chain_id} not in wallet; have: {ids:?}");
}
let owner = wallet.forget_keys(chain_id)?; Try / catch
match wallet.forget_keys(chain_id) {
Ok(owner) => Ok(Some(owner)),
Err(e) if e.to_string().contains("nonexistent chain") => {
// nothing to do; treat as no-op for idempotent scripts
Ok(None)
}
Err(e) => Err(e),
} Prevention
- List chain_ids() before user-triggered forget operations and validate input
- Confirm the wallet file and network match the chain ID being operated on
- Wrap CLI flows so an unknown chain produces a usage message, not a raw error
When it happens
Trigger: Calling wallet.forget_keys(chain_id) with a chain ID that was never added, was already forgotten, belongs to a different wallet file, or was mistyped/truncated on the CLI.
Common situations: Running linera wallet forget-keys after the chain was removed by a previous operation; pointing LINERA_WALLET at the wrong wallet.json; passing a testnet chain ID to a devnet wallet; copy-paste error in the 64-hex-character chain ID.
Related errors
- keypair not found for chain `{chain_id}`
- Default wallet directory is not supported in this platform:
- No chain ID specified and no default chain in wallet
- Chain {chain_id} not found.
- Wallet already exists: {}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/dd7a57bfc6e7e3f5.
Report an issue: GitHub.