linera-io/linera-protocol · error · async_graphql::Error

Request processing was cancelled

Error message

Request processing was cancelled

What it means

The `claim` GraphQL mutation pushes a PendingRequest carrying a oneshot responder onto the faucet's shared queue and then awaits the reply channel. This error means the batch processor dropped that responder without ever sending a PendingResponse, so `rx.await` returned a oneshot RecvError. In practice the faucet's batch-processing task exited (shutdown, fatal batch error, or an early `?` return in `execute_batch` such as a failed `update_wallet`) while the request was queued or in flight. It is a server-side lifecycle failure, not a problem with the claim arguments.

Source

Thrown at linera-faucet/server/src/lib.rs:525

                daily_period: 0,
                responder: tx,
                #[cfg(with_metrics)]
                queued_at: std::time::Instant::now(),
            });

            #[cfg(with_metrics)]
            metrics::QUEUE_SIZE
                .with_label_values(&[])
                .observe(requests.len() as f64);
        }

        // Notify the batch processor that there's a new request.
        self.request_notifier.notify_one();

        // Wait for the result
        let response = rx
            .await
            .map_err(|_| Error::new("Request processing was cancelled"))?;

        #[cfg(with_metrics)]
        {
            // Refusals detected during batch validation (e.g. a duplicate that
            // raced past the front-door check) arrive here as errors; classify
            // them by message so they are counted once, under their own label.
            let label = match &response {
                PendingResponse::Initial(Ok(_)) => "success",
                PendingResponse::Initial(Err(error)) => refusal_label(error).unwrap_or("error"),
                PendingResponse::Daily(_) => "error",
            };
            metrics::CLAIM_REQUESTS_TOTAL
                .with_label_values(&[label])
                .inc();
        }

        match response {
            PendingResponse::Initial(result) => result.map(|b| *b),

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Retry the `claim` after a short backoff — it is safe: if the first attempt actually landed, `do_claim`'s duplicate path (lib.rs:487-494) returns the existing chain description instead of creating a second chain
  2. Check the faucet server logs for `Batch processing error` or `Failed to execute batch` to find the underlying cause that dropped the responder
  3. Verify the faucet's wallet and storage backends are reachable and consistent — a failing `update_wallet` after `execute_operations` drops responders (lib.rs:958-962)
  4. If every claim fails this way, restart the faucet service and investigate why the batch loop is not completing

Example fix

// before
let description = client.claim(owner, None).await?;

// after - treat cancellation as transient; re-claiming is safe
let description = loop {
    match client.claim(owner, None).await {
        Ok(description) => break description,
        Err(e) if e.message.contains("Request processing was cancelled") => {
            tokio::time::sleep(std::time::Duration::from_secs(2)).await;
        }
        Err(e) => return Err(e),
    }
};
Defensive patterns

Strategy: retry

Try / catch

In your GraphQL client, catch the mutation error and match its message; on `Request processing was cancelled` sleep 2-5s (with jitter) and re-issue the same `claim(owner)` — the mutation is idempotent for owners that already hold a chain (the duplicate path returns the existing description). Give up after a few attempts and surface a 'faucet unavailable' state.

Prevention

When it happens

Trigger: Calling the `claim` mutation while the faucet server is shutting down (its CancellationToken fired and the final `process_batch` failed); `execute_batch` failing after operations execute but before responses are sent, e.g. `update_wallet` returning an error via `?` or `extract_opened_single_owner_chains` failing (both drop the responders of popped requests); the batch processor task panicking or the process dying between enqueue and reply.

Common situations: Faucet redeployments/restarts while test or bot clients are claiming; corrupted or locked faucet wallet making `update_wallet` fail; storage or validator outages surfacing as `Batch processing error` in the logs; test harnesses tearing the service down with claims still queued (the pattern exercised by test_faucet_persistence and test_faucet_rate_limiting).

Related errors


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