linera-io/linera-protocol · error · async_graphql::Error
This user has no chain yet
Error message
This user has no chain yet
What it means
The faucet server's chain_id GraphQL query looks up the chain the faucet created for a given AccountOwner; when the storage returns None it fails with this user-facing error. It means the faucet has no record of a claim by that owner — not that the chain doesn't exist on the network. Related queries like initial_claim hit storage the same way and only succeed for owners that already interacted with this faucet.
Source
Thrown at linera-faucet/server/src/lib.rs:370
}
/// Returns the current epoch of the faucet's chain.
async fn current_epoch(&self) -> Result<Epoch, Error> {
let info = self.client.chain_info().await?;
Ok(info.epoch)
}
/// Find the existing chain with the given authentication key, if any.
async fn chain_id(&self, owner: AccountOwner) -> Result<ChainId, Error> {
// Check if this owner already has a chain.
#[cfg(with_metrics)]
let histogram = metrics::DATABASE_OPERATION_LATENCY.with_label_values(&["get_chain_id"]);
#[cfg(with_metrics)]
let _latency = histogram.measure_latency();
let chain_id = self.faucet_storage.get_chain_id(&owner).await?;
chain_id.ok_or_else(|| Error::new("This user has no chain yet"))
}
/// Returns the initial claim for the given owner, if any.
async fn initial_claim(&self, owner: AccountOwner) -> Result<Option<InitialClaim>, Error> {
let claim_record = self.faucet_storage.initial_claim(&owner).await?;
Ok(claim_record.map(|r| InitialClaim {
chain_id: r.chain_id,
timestamp: r.timestamp,
}))
}
/// Returns the earliest time at which the owner can make a daily claim.
/// If the returned timestamp is in the past (or now), the user can claim immediately.
/// Returns `None` if the user has not yet completed the initial claim.
async fn next_daily_claim(&self, owner: AccountOwner) -> Result<Option<Timestamp>, Error> {
let initial_claim = match self.faucet_storage.initial_claim(&owner).await? {
Some(record) => record,View on GitHub (pinned to 6c226ddcb3)
Solutions
- Claim a chain from the faucet first: run the faucet's claim mutation (or the README example's faucet call) for that exact owner key, then re-query chain_id.
- Verify the owner value: recompute it from the same private key/derivation used at claim time and use its canonical formatting (0x-prefixed hex) in the query.
- If the faucet storage was wiped or you switched faucet instances, re-run the claim against the current faucet — records are per-faucet, not global.
Example fix
# before: querying before any claim
query { chainId(owner: "0xYOUR_OWNER") } # -> "This user has no chain yet"
# after: claim once, then query
mutation { claim(owner: "0xYOUR_OWNER") { messageId } }
query { chainId(owner: "0xYOUR_OWNER") } # returns the assigned chain Defensive patterns
Strategy: fallback
Validate before calling
// No cheap pre-check exists server-side; probe by treating this error as the signal: // (claim flow fills the role of validation — see tryCatchPattern)
Try / catch
match faucet_client.chain_id(owner).await {
Ok(chain_id) => chain_id,
Err(e) if e.message == "This user has no chain yet" => {
// fall back: claim a chain for this owner, then retry once
faucet_client.claim(owner).await?;
faucet_client.chain_id(owner).await?
}
Err(e) => return Err(e.into()),
} Prevention
- Always run the faucet claim before any chain_id query in example scripts and onboarding flows.
- Derive the owner from one fixed key/derivation path and reuse it verbatim (canonical 0x hex) across claim and query.
- Remember faucet storage is per-instance: after wiping or switching a faucet, re-claim before querying.
When it happens
Trigger: Querying chain_id(owner: "0x…") against the faucet GraphQL endpoint for an owner that never claimed from this faucet (or whose claim used a different owner address), e.g. following the faucet example but skipping the claim step, or querying a fresh/dev faucet database.
Common situations: Running the faucet example scripts out of order (query before the claim mutation); pointing the client at a freshly restarted faucet whose storage was wiped; re-deriving the owner from a different key/derivation path so the address no longer matches the one used at claim time; reading someone else's chain from a faucet they never used.
Related errors
- Request processing was cancelled
- Unexpected response type
- no admin chain (Root(0)) in genesis config
- expected whitespace after 'query' keyword
- expected an operation name after 'query', e.g. 'query MyQuer
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/f38f66eabefbde5b.
Report an issue: GitHub.