linera-io/linera-protocol · error

no errors present but no data returned

Error message

no errors present but no data returned

What it means

linera-faucet-client's query method (linera-faucet/client/src/lib.rs) posts a GraphQL query and inspects the response envelope. When the envelope contains no `errors` but `data` is null, it expects data to be present - so a 200 response whose body has data:null panics the client. This means the server answered successfully but produced no data, which in practice is a client/server schema or version mismatch or a faucet bug, not a transport failure.

Source

Thrown at linera-faucet/client/src/lib.rs:153

                .filter_map(|error| {
                    error
                        .get("message")
                        .and_then(|msg| msg.as_str())
                        .map(|s| s.to_string())
                })
                .collect::<Vec<_>>();

            if messages.is_empty() {
                Err(Error::GraphQl(errors))
            } else {
                Err(Error::GraphQl(vec![serde_json::Value::String(
                    messages.join("; "),
                )]))
            }
        } else {
            Ok(response
                .data
                .expect("no errors present but no data returned"))
        }
    }

    /// Fetches the network's genesis configuration from the faucet.
    pub async fn genesis_config(&self) -> Result<GenesisConfig, Error> {
        #[derive(serde::Deserialize)]
        #[serde(rename_all = "camelCase")]
        struct Response {
            genesis_config: GenesisConfig,
        }

        Ok(self
            .query::<Response>("query { genesisConfig }")
            .await?
            .genesis_config)
    }

    /// Fetches the faucet's version information.

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Check faucet and client versions match: query `query { version }` via curl and compare with your linera release.
  2. Point the client at the correct faucet URL for your network (the faucet URL shipped with your linera version).
  3. Reproduce with curl to inspect the raw body: `curl -s <url> -H 'content-type: application/json' -d '{"query":"query { version }"}'` and check whether data is null.
  4. Upgrade or downgrade linera so client and faucet come from the same release.
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe the faucet before real queries: a cheap query both proves reachability
// and lets you pin the expected version.
let version = faucet_client.version_info().await?;
if version.major != EXPECTED_FAUCET_MAJOR {
    anyhow::bail!("faucet version {version} does not match client expectation {EXPECTED_FAUCET_MAJOR}");
}

Try / catch

// The library panics rather than returning Err; isolate calls with catch_unwind:
let outcome = std::panic::catch_unwind(AssertUnwindSafe(|| {
    block_on(faucet_client.genesis_config())
}));
match outcome {
    Ok(Ok(config)) => Ok(config),
    Ok(Err(e)) => Err(e.into()),
    Err(_) => Err(anyhow::anyhow!("faucet returned 200 but no data; client/server version mismatch?")),
}

Prevention

When it happens

Trigger: Calling faucet client APIs (genesis_config, version_info, claim, etc.) against a faucet server whose GraphQL schema differs from the client's expectation - e.g. renamed fields, different casing, or an older/newer faucet release. Also a proxy or gateway that rewrites the body and drops the data field.

Common situations: linera CLI (with built-in faucet client) pointed at a faucet of a different release; devnet faucet updated while the local CLI stayed on an older version; URL pointing at a generic GraphQL endpoint instead of the faucet.

Related errors


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