Skip to content

Chain-log/block subscription with an unconfigured chain_id fails open instead of failing at boot #65

Description

@lgahdl

Summary

A module's [[subscription]] entry naming a chain_id with no matching [chains.<id>] entry in engine.toml is not caught at boot. The engine boots successfully and the subscription's background task retries forever with only a periodic warn-level log — it never receives an event and never causes a startup failure.

Affected code

  • crates/nexum-runtime/src/supervisor.rs — per-module subscription validation loop (module load sequence)
  • crates/nexum-runtime/src/runtime/event_loop.rsreconnecting_chain_log_task() / reconnecting_block_task()
  • crates/nexum-runtime/src/host/provider_pool.rsProviderPool chain lookups

Finding

The only boot-time validation of [[subscription]] entries checks two cases: Cron subscriptions (warns, since they're inert in 0.2) and Extension subscriptions naming an unknown event kind (hard boot error). Every other subscription kind — including chain-log and block subscriptions — falls through a _ => {} catch-all with zero validation.

open_chain_log_streams/open_block_streams spawn a reconnect task for every subscription unconditionally, with no eager chain-existence check before spawning. That task's first pool.block_number(chain) call returns ProviderError::UnknownChain, and the task's error-handling path treats this identically to a transient network failure: log a warn!, apply exponential backoff, and retry forever. There's no special case distinguishing "this chain will never exist" from "the RPC is briefly down."

Impact

The engine boots successfully, every module initializes, and everything looks healthy except for a recurring warn-level "chain-log head fetch failed — retrying after backoff" log line for a subscription that will never receive a single event. This is easy to miss in production log volume and gives no clear signal that a module is effectively dead on arrival due to a config typo (e.g. a chain_id that doesn't match any [chains.<id>] entry).

Suggested fix

Extend the existing subscription-validation loop to also check chain-log/block subscription chain_ids against engine_cfg.chains.keys(), returning a hard boot error on a mismatch — mirroring what already happens for unknown extension kinds.

Found via

Internal red-team exercise (operator mistake persona).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions