engine_forkchoiceUpdatedV4 rejects a call that passes the spec's third parameter, so a
spec-conformant caller cannot drive forkchoice on an Amsterdam chain.
Expected
Per amsterdam.md,
the method takes three parameters:
forkchoiceState
payloadAttributes: Object|null
custodyColumns: DATA|null, 16 bytes
The third has been in the spec since ethereum/execution-apis#774 (2026-05-01) and is nullable, so
a call passing null for it should be accepted.
Actual
Invalid params: Expected 2 or 1 params
parse_v4 accepts only one or two parameters
(crates/networking/rpc/engine/fork_choice.rs#L513):
if params.len() != 2 && params.len() != 1 {
return Err(RpcErr::BadParams("Expected 2 or 1 params".to_owned()));
}
ForkChoiceUpdatedV4 correspondingly has no field for it
(#L134-L137),
and its From<ForkChoiceUpdatedV4> for RpcRequest serialises two params
(#L139-L150),
so ethrex's own client side does not exercise the third parameter either.
Reproduce
Against any Amsterdam-configured ethrex:
curl -s -X POST -H 'Content-Type: application/json' --data '{
"jsonrpc":"2.0","id":1,"method":"engine_forkchoiceUpdatedV4",
"params":[{"headBlockHash":"0x…","safeBlockHash":"0x…","finalizedBlockHash":"0x…"},null,null]
}' http://127.0.0.1:8551
Observed with ethrex/v20.0.0-glamsterdam-devnet-7-e4e7483d (ethpandaops/ethrex:glamsterdam-devnet-7);
the same two-parameter shape is on main.
It also shows up through hive's ethereum/rpc-compat simulator against an Amsterdam chain, whose
headfcu.json is a three-parameter forkchoiceUpdatedV4. The simulator's client launch check
fails only when the client returns an error to that call — a SYNCING status passes — so the
launch is recorded as failed and no tests run.
Note on scope
This is independent of #6954 / #5504. Those cover importing pre-merge fixture chains, which is a
separate axis: ethrex will not import the pre-merge prefix of that chain regardless, and this
report is only about the parameter count being rejected before any of that matters. Fixing this
alone would let ethrex start against an Amsterdam chain; it would still serve a genesis-only chain
until the pre-merge question is settled separately.
Erigon has the same gap with a different message, for cross-reference: erigontech/erigon#22896.
Found while bringing up a Glamsterdam rpc-compat matrix in execution-apis; happy to test a fix
against that setup.
engine_forkchoiceUpdatedV4rejects a call that passes the spec's third parameter, so aspec-conformant caller cannot drive forkchoice on an Amsterdam chain.
Expected
Per amsterdam.md,
the method takes three parameters:
forkchoiceStatepayloadAttributes:Object|nullcustodyColumns:DATA|null, 16 bytesThe third has been in the spec since ethereum/execution-apis#774 (2026-05-01) and is nullable, so
a call passing
nullfor it should be accepted.Actual
parse_v4accepts only one or two parameters(
crates/networking/rpc/engine/fork_choice.rs#L513):ForkChoiceUpdatedV4correspondingly has no field for it(
#L134-L137),and its
From<ForkChoiceUpdatedV4> for RpcRequestserialises two params(
#L139-L150),so ethrex's own client side does not exercise the third parameter either.
Reproduce
Against any Amsterdam-configured ethrex:
Observed with
ethrex/v20.0.0-glamsterdam-devnet-7-e4e7483d(ethpandaops/ethrex:glamsterdam-devnet-7);the same two-parameter shape is on
main.It also shows up through hive's
ethereum/rpc-compatsimulator against an Amsterdam chain, whoseheadfcu.jsonis a three-parameterforkchoiceUpdatedV4. The simulator'sclient launchcheckfails only when the client returns an error to that call — a
SYNCINGstatus passes — so thelaunch is recorded as failed and no tests run.
Note on scope
This is independent of #6954 / #5504. Those cover importing pre-merge fixture chains, which is a
separate axis: ethrex will not import the pre-merge prefix of that chain regardless, and this
report is only about the parameter count being rejected before any of that matters. Fixing this
alone would let ethrex start against an Amsterdam chain; it would still serve a genesis-only chain
until the pre-merge question is settled separately.
Erigon has the same gap with a different message, for cross-reference: erigontech/erigon#22896.
Found while bringing up a Glamsterdam
rpc-compatmatrix in execution-apis; happy to test a fixagainst that setup.