FuelLabs/fuel-core · error · anyhow::Error
Invalid latest stream entry height
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.
Solutions
- Inspect the offending entry with XRANGE {lease_key}:block:stream - + and identify the malformed height field
- Align all fuel-core nodes to one version and one lease_key so the record format is consistent
- 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
- Use a unique lease_key per chain/deployment so streams are never shared
- Upgrade all nodes in lockstep; do not mix fuel-core versions on one stream
- Restrict write access to the Redis stream to the fuel-core user only
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
- Backlog unresolved at height
- Backlog unresolved at height
- Failed to read latest stream entry from Redis node
- Failed to read stream entries from Redis node
- Timed out reading latest stream entry from Redis node
AI-assisted analysis of FuelLabs/fuel-core@add100d30d (2026-09-05).
Data as JSON: /api/errors/2db762956d525c76.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fuel-core/src/service/adapters/consensus_module/poa.rs:1462
.await;
Err(anyhow!(
"Timed out reading latest stream entry from Redis node"
))
}
Ok(Err(e)) => {
RedisLeaderLeaseAdapter::clear_cached_connection_for(&self.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())))
}
}
}
}
/// RAII guard that increments `poa_outstanding_publish_tasks` on
/// construction and decrements on drop. Constructed in the parent of
/// `publish_block_on_all_nodes` (so the gauge counts the task from the
/// instant it is queued) and moved into the spawn closure (so the
/// decrement runs whether the task completes normally, panics inside
/// the closure, or is cancelled mid-await).
struct OutstandingPublishTaskGuard;
impl OutstandingPublishTaskGuard {
fn new() -> Self {
poa_metrics().outstanding_publish_tasks.inc();
SelfView on GitHub (pinned to add100d30d)