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

Invalid latest stream entry height: {e}

Error message

Invalid latest stream entry height: {e}

What it means

read_latest_stream_entry_on_node (crates/fuel-core/src/service/adapters/consensus_module/poa.rs:637): the Lua script returned a 2-element [height, id] result but entry[0] failed to parse as u32. Block publish writes the height field as a plain decimal height, so anything unparseable means the stream content is malformed relative to what this code expects.

Source

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

            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,
    ) -> anyhow::Result<bool> {
        let next_height = u32::from(next_height);
        let latest_results = futures::future::join_all(
            self.redis_nodes
                .iter()
                .map(|redis_node| self.read_latest_stream_entry_on_node(redis_node)),
        )
        .await;
        let mut successful_reads = 0usize;
        let mut failed_count = 0usize;

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Inspect the offending entry with XRANGE {lease_key}:block:stream - + and identify the malformed height field
  2. Align all fuel-core nodes to one version and one lease_key so the record format is consistent
  3. As a last resort delete/recreate the stream once the backlog is reconciled or consciously abandoned — this forces backlog recovery from other sources

Example fix

redis-cli XRANGE <lease_key>:block:stream - + COUNT 20
# find the entry whose first field is not a decimal height, then:
# redis-cli XDEL <lease_key>:block:stream <entry-id>
Defensive patterns

Strategy: try-catch

Validate before calling

// operator-side check that stream heights are decimal u32:
// redis-cli XRANGE <lease_key>:block:stream - + COUNT 5
// every entry's first field must be a plain decimal height

Type guard

fn is_invalid_stream_height(e: &anyhow::Error) -> bool {
    e.to_string().contains("Invalid latest stream entry height")
}

Try / catch

match read_latest(node).await {
    Err(e) if is_invalid_stream_height(&e) => {
        // corrupt/foreign stream data: quarantine node, inspect with XRANGE,
        // never rewrite data blindly — reconcile with other nodes first
    }
    other => other,
}

Prevention

When it happens

Trigger: Foreign or corrupted data in the {lease_key}:block:stream stream: a different writer or record format, a partially written entry after a Redis crash, or a fuel-core version that changed the stream record layout.

Common situations: Mixing fuel-core versions against the same Redis and lease_key; manual writes to the stream; corrupted RDB/AOF restore artifacts.

Related errors


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