When forwarding is enabled and the forwarder address cannot be resolved
(e.g. RPC unavailable at node boot), GetEVMEffectiveTransmitterID
previously logged a warning and silently fell back to the EOA. That EOA
was then baked into the effective transmitter, permanently disabling
forwarding for the process lifetime so the job could not transmit and did
not recover without a restart.
Return the error instead so a forwarding job either uses its forwarder or
fails honestly (recorded and retried on the next boot once RPC is warm).
DF-25025
Motivation
When forwarding is enabled, the node determines the OCR transmitter by resolving the forwarder contract for the configured EOA via an RPC call at job startup. If that RPC call fails — most commonly because the EVM
MultiNodehas not selected a live RPC yet during node boot (no live nodes available) — the previous code logged a warning and silently fell back to the EOA.That fallback is sticky and harmful:
ocr2FeedsTransmitter), the tx-time forwarder lookup is gated onslices.Contains(fromAddresses, effectiveTransmitterAddress), so once the EOA is the effective address, forwarding is permanently disabled.This is the DF-25025 reliability issue: an RPC blip at boot leaves forwarding jobs running on the wrong transmitter until they are manually restarted.
Change
Remove the forwarder→EOA fallback so a forwarding-enabled job either uses its forwarder or fails honestly. On forwarder-resolution failure the service now returns the error, which the job spawner records (
TryRecordError) and re-attempts on the next boot — when the RPC is warm and the correct forwarder can be resolved.core/services/ocr2/delegate.go(GetEVMEffectiveTransmitterID): return theGetForwarderForEOAerror instead ofWarnw+ returning the EOA.core/services/ocr/delegate.go(ServicesForSpec): same treatment for the OCR1 forwarding path.Behavior change / risk
Forwarding-enabled jobs will now fail to start when the forwarder cannot be resolved at boot (e.g. cold RPC), where they previously started on the EOA. This is intended: an explicit, recorded failure that self-heals on the next boot is preferable to a silent, unrecoverable misconfiguration. This matches the existing "recovers on restart" behavior operators already rely on.
Scope is limited to the boot-time transmitter determination. The tx-time EOA fallbacks in the Median transmitter and broader boot-time RPC resilience (e.g. spawner retry, log-poller
RegisterFilter/CodeAttolerance) are intentionally out of scope.Testing
go build ./core/services/ocr2/ ./core/services/ocr/go test ./core/services/ocr2/(incl.TestGetEVMEffectiveTransmitterID, updated to assert an error rather than the EOA fallback)go test ./core/services/ocr/