Skip to content

trace_filter can mix error objects into a successful Array<TraceEntry> result #23128

Description

@BenWhite713

Summary

The documentation defines the trace_filter result as:

Array<TraceEntry> — flat list of call frames that match the filter

Some per-transaction failures are instead serialized as error-shaped objects inside that array while the JSON-RPC envelope reports success.

Observed response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "error": {
        "code": -32000,
        "message": "protected txn is not supported by signer ..."
      }
    }
  ]
}

The array item is not a TraceEntry and has no type, action, or traceAddress fields.

Affected revision

Reproduction

The deterministic fixture mines an EIP-155-protected legacy transaction at block 3, then calls trace_filter for that block with a block-number override of 1. The overridden pre-Spurious-Dragon signer cannot decode the protected transaction.

RPC_URL="${RPC_URL:-http://127.0.0.1:8545}"
BLOCK="0x3"
TO_ADDRESS="0x71562b71999873DB5b286dF957af199Ec94617F7"

curl -s -H 'Content-Type: application/json' --data \
  '{"jsonrpc":"2.0","id":1,"method":"trace_filter","params":[{"fromBlock":"'"$BLOCK"'","toBlock":"'"$BLOCK"'","toAddress":["'"$TO_ADDRESS"'"]},false,{"blockOverrides":{"number":"0x1"}}]}' \
  "$RPC_URL"

The public HTTP JSON-RPC fixture returned the successful envelope shown above. Erigon's existing TestFilterSignerReflectsBlockOverridesNumber exercises the same per-transaction failure behavior at the method level.

The HTTP fixture is reproducible in the research checkout with:

cd path_to/erigon
go test \
  -overlay="path_to/overlay.json" \
  ./rpc/jsonrpc \
  -run '^TestValidationTraceFilterCanMixErrorObjectIntoSuccessfulResult$' \
  -count=1 -v

Relevant code

For example, rpc/jsonrpc/trace_filtering.go:593-603 handles an AsMessage failure by writing rpc.HandleError inside the result array and continuing:

msg, err := txn.AsMessage(*lastSigner, &lastBaseFee, lastRules)
if err != nil {
    // array delimiter handling omitted
    stream.WriteObjectStart()
    rpc.HandleError(err, stream)
    stream.WriteObjectEnd()
    continue
}

The method later closes the array and returns nil, so the outer RPC response is successful. Similar per-item serialization exists for several other iterator, lookup, and execution failures.

Expected behavior / clarification requested

Please choose one explicit result contract:

  1. fail the JSON-RPC request when a transaction cannot be traced;
  2. return only valid TraceEntry items and expose partial failures separately;
  3. document a union element type such as TraceEntry | TraceItemError, including
    how clients should detect incomplete results.

Impact

Strict decoders expecting Array<TraceEntry> can fail on an otherwise successful response. Callers that ignore unknown item shapes may silently treat a partial trace as complete.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions