FuelLabs/fuel-core · error · anyhow::Error

Failed to read latest stream entry from Redis node: {e}

Error message

Failed to read latest stream entry from Redis node: {e}

What it means

Same read path (crates/fuel-core/src/service/adapters/consensus_module/poa.rs:627): the Lua script completed but Redis returned a protocol-level error, carried in {e}. The cached connection is cleared before propagating; if enough other nodes answer, quorum-based reconciliation continues without the failed node.

Source

Thrown at crates/fuel-core/src/service/adapters/consensus_module/poa.rs:627

    ) -> anyhow::Result<Option<(u32, String)>> {
        let mut connection = self.multiplexed_connection(redis_node).await?;
        let latest_entry = timeout(
            self.node_timeout,
            redis::Script::new(READ_LATEST_STREAM_ENTRY_SCRIPT)
                .key(&self.block_stream_key)
                .invoke_async::<Vec<String>>(&mut connection),
        )
        .await;
        match latest_entry {
            Err(_) => {
                self.clear_cached_connection(redis_node).await;
                Err(anyhow!(
                    "Timed out reading latest stream entry from Redis node"
                ))
            }
            Ok(Err(e)) => {
                self.clear_cached_connection(redis_node).await;
                Err(anyhow!(
                    "Failed to read latest stream entry from Redis node: {e}"
                ))
            }
            Ok(Ok(entry)) => {
                if entry.len() != 2 {
                    return Ok(None);
                }
                let height = entry[0]
                    .parse::<u32>()
                    .map_err(|e| anyhow!("Invalid latest stream entry height: {e}"))?;
                Ok(Some((height, entry[1].clone())))
            }
        }
    }

    async fn should_reconcile_from_stream(
        &self,
        next_height: BlockHeight,

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Read the {e} cause: WRONGTYPE means the block:stream key is not a stream — remove or rename the foreign key after reviewing data loss
  2. Fix Redis health: free disk space (MISCONF), correct ACL/credentials
  3. Restart or replace the unhealthy node; a quorum of healthy nodes keeps the chain operating meanwhile

Example fix

# WRONGTYPE case: inspect and clear the foreign key
redis-cli -u <url> TYPE <lease_key>:block:stream   # -> string (bad)
redis-cli -u <url> DEL  <lease_key>:block:stream   # stream is recreated on next publish
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight type check per node:
let key_type: String = cmd("TYPE").arg(&stream_key).query(&mut con)?;
anyhow::ensure!(key_type == "stream", "block:stream key is not a stream");

Try / catch

match read_latest(node).await {
    Err(e) if e.to_string().contains("Failed to read latest stream entry") => {
        // inspect root cause in {e}: WRONGTYPE/MISCONF/NOAUTH each have a distinct fix;
        // exclude node this round, alert if quorum margin is gone
    }
    other => other,
}

Prevention

When it happens

Trigger: Redis errors such as WRONGTYPE ({lease_key}:block:stream holds a non-stream value), MISCONF (persistence failure, read-only state), NOAUTH/ACL denials, or an in-flight connection killed server-side.

Common situations: Another tool overwrote the stream key with a plain string; Redis hit disk-full and entered MISCONF; credentials or ACLs changed under the node; aggressive server timeout policies dropping idle connections.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/909aa94bdb59d5b2. Report an issue: GitHub.