{"record":{"id":"f38f66eabefbde5b","repo":"linera-io/linera-protocol","slug":"this-user-has-no-chain-yet","errorCode":null,"errorMessage":"This user has no chain yet","messagePattern":"This user has no chain yet","errorType":"validation","errorClass":"async_graphql::Error","httpStatus":null,"severity":"error","filePath":"linera-faucet/server/src/lib.rs","lineNumber":370,"sourceCode":"    }\n\n    /// Returns the current epoch of the faucet's chain.\n    async fn current_epoch(&self) -> Result<Epoch, Error> {\n        let info = self.client.chain_info().await?;\n        Ok(info.epoch)\n    }\n\n    /// Find the existing chain with the given authentication key, if any.\n    async fn chain_id(&self, owner: AccountOwner) -> Result<ChainId, Error> {\n        // Check if this owner already has a chain.\n        #[cfg(with_metrics)]\n        let histogram = metrics::DATABASE_OPERATION_LATENCY.with_label_values(&[\"get_chain_id\"]);\n        #[cfg(with_metrics)]\n        let _latency = histogram.measure_latency();\n\n        let chain_id = self.faucet_storage.get_chain_id(&owner).await?;\n\n        chain_id.ok_or_else(|| Error::new(\"This user has no chain yet\"))\n    }\n\n    /// Returns the initial claim for the given owner, if any.\n    async fn initial_claim(&self, owner: AccountOwner) -> Result<Option<InitialClaim>, Error> {\n        let claim_record = self.faucet_storage.initial_claim(&owner).await?;\n\n        Ok(claim_record.map(|r| InitialClaim {\n            chain_id: r.chain_id,\n            timestamp: r.timestamp,\n        }))\n    }\n\n    /// Returns the earliest time at which the owner can make a daily claim.\n    /// If the returned timestamp is in the past (or now), the user can claim immediately.\n    /// Returns `None` if the user has not yet completed the initial claim.\n    async fn next_daily_claim(&self, owner: AccountOwner) -> Result<Option<Timestamp>, Error> {\n        let initial_claim = match self.faucet_storage.initial_claim(&owner).await? {\n            Some(record) => record,","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-faucet/server/src/lib.rs#L352-L388","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: querying before any claim\nquery { chainId(owner: \"0xYOUR_OWNER\") }   # -> \"This user has no chain yet\"\n\n# after: claim once, then query\nmutation { claim(owner: \"0xYOUR_OWNER\") { messageId } }\nquery { chainId(owner: \"0xYOUR_OWNER\") }   # returns the assigned chain","handlingStrategy":"fallback","validationCode":"// No cheap pre-check exists server-side; probe by treating this error as the signal:\n// (claim flow fills the role of validation — see tryCatchPattern)","typeGuard":null,"tryCatchPattern":"match faucet_client.chain_id(owner).await {\n    Ok(chain_id) => chain_id,\n    Err(e) if e.message == \"This user has no chain yet\" => {\n        // fall back: claim a chain for this owner, then retry once\n        faucet_client.claim(owner).await?;\n        faucet_client.chain_id(owner).await?\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["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."],"tags":["rust","graphql","faucet","linera","account"],"backgroundTag":"account-not-found","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}