Hi Folks - I'm new to OP Stack, so apologies in advance if I am misunderstanding anything. Thanks in advance for the help.
System information
Geth version: op-geth (path-based state scheme, --state.scheme=path)
CL client & version: op-node
OS & Version: Linux
Commit hash: optimism branch (HEAD)
Expected behaviour
When op-node's derivation pipeline lags significantly behind op-geth's chain tip, makeEnv() in the block builder should be able to build blocks from any parent for which the node maintains state.
For path-based nodes, if the desired parent is beyond the 128-block in-memory diff layer limit, the node should fall back to reconstructing parent state from the on-disk state history (for path-based nodes this would be controlled by --history.state, which defaults to 90,000 blocks).
Actual behaviour
When the parent block is more than ~128 blocks behind op-geth's chain tip, StateAt() fails with missing trie node because the state root is no longer in the in-memory diff layers.
Importantly, the StateAtBlock() fallback, which would access the on-disk state history, is never reached.
This is as a result of two issues:
makeEnv() returns early on StateAt failure before the fallback is reached.
- Since the miner's backend is
*Ethereum, the BackendWithHistoricalState type assertion always fails, because it doesn't export the expected StateAtBlock()
The result is that the missing trie node error propagates as InvalidPayloadAttributes back to op-node, which results in a critical error.
Steps to reproduce the behaviour
- Run op-geth with
--state.scheme=path (default --history.state=90000)
- Run op-node in a configuration where the unsafe head can advance ahead of the safe head (e.g., EL sync mode, or any scenario where the derivation pipeline falls behind - slow L1 RPC, pipeline reset, etc.)
- Allow a gap of >128 blocks to form between the derivation pipeline position and op-geth's chain tip
- The derivation pipeline attempts to build a block whose parent is >128 blocks behind the tip
- op-node crashes with a critical error
Backtrace
t=2026-02-23T03:47:34+0000 lvl=warn msg="Failed to share forkchoice-updated signal" state="&{HeadBlockHash:0xb73b4c37b464328eb7ac0ba71c638776f74a9ddfd865ce994e18bb3682f6a125 SafeBlockHash:0xb73b4c37b464328eb7ac0ba71c638776f74a9ddfd865ce994e18bb3682f6a125 FinalizedBlockHash:0x760bb4f929f7e2bca8522272fe6b2015bc27c851b3e68c13a51be3b977a59764}" err="Invalid payload attributes: map[err:missing trie node 6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 (path ) state 0x6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 is not available]"
t=2026-02-23T03:47:34+0000 lvl=warn msg="could not process payload attributes" err="payload attributes are not valid, cannot build block: Invalid payload attributes: map[err:missing trie node 6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 (path ) state 0x6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 is not available]"
t=2026-02-23T03:47:34+0000 lvl=error msg="deposit only block was invalid" parent=0xb73b4c37b464328eb7ac0ba71c638776f74a9ddfd865ce994e18bb3682f6a125:35837047 err="payload attributes are not valid, cannot build block: Invalid payload attributes: map[err:missing trie node 6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 (path ) state 0x6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 is not available]"
t=2026-02-23T03:47:34+0000 lvl=error msg="Critical error" err="failed to process block with only deposit transactions: payload attributes are not valid, cannot build block: Invalid payload attributes: map[err:missing trie node 6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 (path ) state 0x6c4f0d2f78ef26de99ed4b0a2af945c0cd43c7d759d73e7d9f44649f75cee471 is not available]"
Hi Folks - I'm new to OP Stack, so apologies in advance if I am misunderstanding anything. Thanks in advance for the help.
System information
Geth version: op-geth (path-based state scheme, --state.scheme=path)
CL client & version: op-node
OS & Version: Linux
Commit hash: optimism branch (HEAD)
Expected behaviour
When op-node's derivation pipeline lags significantly behind op-geth's chain tip,
makeEnv()in the block builder should be able to build blocks from any parent for which the node maintains state.For path-based nodes, if the desired parent is beyond the 128-block in-memory diff layer limit, the node should fall back to reconstructing parent state from the on-disk state history (for path-based nodes this would be controlled by
--history.state, which defaults to 90,000 blocks).Actual behaviour
When the parent block is more than ~128 blocks behind op-geth's chain tip,
StateAt()fails with missing trie node because the state root is no longer in the in-memory diff layers.Importantly, the
StateAtBlock()fallback, which would access the on-disk state history, is never reached.This is as a result of two issues:
makeEnv()returns early onStateAtfailure before the fallback is reached.*Ethereum, theBackendWithHistoricalStatetype assertion always fails, because it doesn't export the expectedStateAtBlock()The result is that the missing trie node error propagates as
InvalidPayloadAttributesback to op-node, which results in a critical error.Steps to reproduce the behaviour
--state.scheme=path(default --history.state=90000)Backtrace