linera-io/linera-protocol · critical · anyhow::Error
The chain with the ID returned by the faucet is not owned by
Error message
The chain with the ID returned by the faucet is not owned by you. Please make sure you are connecting to a genuine faucet.
What it means
During `linera wallet request-chain --faucet <URL>` the CLI generates a fresh key, asks the faucet for a chain via claim_to, then verifies the returned ChainDescription actually lists that key as an owner. If the faucet hands back a chain owned by someone else, this check fails — the classic signature of a fake or man-in-the-middle faucet.
Source
Thrown at linera-service/src/cli/main.rs:1832
}) => {
let start_time = Instant::now();
let owner: AccountOwner = keystore.generate_key().await?.into();
info!(
"Requesting a new chain for owner {owner} using the faucet at address \
{faucet_url}",
);
let destination = if fund_owner_account {
owner
} else {
AccountOwner::CHAIN
};
let description = cli_wrappers::Faucet::new(faucet_url)
.claim_to(&owner, &destination)
.await?;
ensure!(
description.config().ownership.is_owner(&owner),
"The chain with the ID returned by the faucet is not owned by you. \
Please make sure you are connecting to a genuine faucet."
);
wallet.insert(
description.id(),
&wallet::Chain {
owner: Some(owner),
..(&description).into()
},
)?;
if set_default {
wallet.set_default_chain(description.id())?;
}
let context = optionsView on GitHub (pinned to 6c226ddcb3)
Solutions
- Verify the faucet URL against the network's official documentation (exact scheme, host, port)
- Re-run against a known-genuine faucet and never use the returned chain even if the command partially succeeded
- If you operate the faucet, check its genesis and chain-assignment logic: it must assign ownership to the requesting owner
- Treat repeat occurrences as a security incident: rotate keys and audit which endpoint produced them
Example fix
// before
let description = Faucet::new(faucet_url).claim_to(&owner, &destination).await?; // trust blindly
// after
let description = Faucet::new(faucet_url).claim_to(&owner, &destination).await?;
ensure!(
description.config().ownership.is_owner(&owner),
"faucet returned a chain we do not own -- do not use it"
); Defensive patterns
Strategy: validation
Validate before calling
let description = Faucet::new(faucet_url).claim_to(&owner, &destination).await?;
if !description.config().ownership.is_owner(&owner) {
anyhow::bail!("faucet returned a chain not owned by us -- refusing to import it");
} Type guard
fn chain_owned_by(description: &ChainDescription, owner: &AccountOwner) -> bool {
description.config().ownership.is_owner(owner)
} Prevention
- Use faucet URLs only from the network's official documentation/genesis
- Always re-verify ownership before importing a faucet-returned chain into a wallet
- Prefer HTTPS faucet endpoints and verify TLS certificates
When it happens
Trigger: Running `linera wallet request-chain --faucet ...` (with or without fund-owner-account) where the faucet's claim_to response describes a chain whose ownership does not include the newly generated owner key.
Common situations: Typo-squatted or spoofed faucet URLs copied from tutorials; a MITM proxy rewriting responses; connecting a wallet to a faucet from a different network or genesis than intended.
Related errors
- Chain {chain_id} not found.
- Wallet already exists: {}
- please specify one of `--faucet` or `--genesis`.
- No default chain found for client
- nonexistent chain `{chain_id}`
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/be2cf8fc7e5e9a05.
Report an issue: GitHub.