ethereum/go-ethereum · error
invalid chainID %v
Error message
invalid chainID %v
What it means
newModernSigner constructs the modern EIP-2718 signer and requires a positive chain ID. A nil or non-positive chain ID cannot be used for EIP-155 replay protection or for signing any typed transaction envelope, so the constructor panics immediately rather than producing a broken signer.
Source
Thrown at core/types/transaction_signing.go:206
}
// txtypeSet is a bitmap for transaction types.
type txtypeSet [2]uint64
func (v *txtypeSet) set(txType byte) {
v[txType/64] |= 1 << (txType % 64)
}
func (v *txtypeSet) has(txType byte) bool {
if txType >= byte(len(v)*64) {
return false
}
return v[txType/64]&(1<<(txType%64)) != 0
}
func newModernSigner(chainID *big.Int, fork forks.Fork) Signer {
if chainID == nil || chainID.Sign() <= 0 {
panic(fmt.Sprintf("invalid chainID %v", chainID))
}
s := &modernSigner{
chainID: chainID,
}
// configure legacy signer
switch {
case fork >= forks.SpuriousDragon:
s.legacy = NewEIP155Signer(chainID)
case fork >= forks.Homestead:
s.legacy = HomesteadSigner{}
default:
s.legacy = FrontierSigner{}
}
s.txtypes.set(LegacyTxType)
// configure tx types
if fork >= forks.Berlin {
s.txtypes.set(AccessListTxType)
}View on GitHub (pinned to 6bb0588ad8)
Solutions
- Pass a strictly positive chain ID, e.g. big.NewInt(1337), when constructing the signer.
- Check the genesis/config: ensure 'chainId' in chainConfig is >= 1 and is loaded before the signer is created.
- Guard call sites with a nil/zero check and fail with a clear error instead of letting the library panic.
Example fix
// before
signer := types.LatestSignerForChainID(nil) // panics
// after
chainID := big.NewInt(1)
if cfg.ChainID != nil && cfg.ChainID.Sign() > 0 {
chainID = cfg.ChainID
}
signer := types.LatestSignerForChainID(chainID) Defensive patterns
Strategy: validation
Validate before calling
func validChainID(id *big.Int) bool {
return id != nil && id.Sign() > 0
}
// use before constructing the signer
if !validChainID(cfg.ChainID) {
return fmt.Errorf("chain id must be positive, got %v", cfg.ChainID)
}
signer := types.LatestSignerForChainID(cfg.ChainID) Try / catch
Not applicable — validate the chain ID before the call; recovering from this panic would leave you without a valid signer anyway.
Prevention
- Always default missing chain IDs to a positive constant in tooling (e.g. 1 for mainnet).
- Assert config.ChainID != nil && Sign() > 0 right after loading genesis.
- Reject --chainid flags parsed as 0 or negative at CLI parse time.
When it happens
Trigger: Calling types.NewModernSigner (or a wrapper such as LatestSignerForChainID / MakeSigner with a config whose ChainID is nil or <= 0); e.g. chainID = big.NewInt(0) or a nil *big.Int from an uninitialized chain config.
Common situations: Private/dev chains mistakenly configured with chain ID 0; code that reads ChainConfig.ChainID before the genesis is loaded and passes nil; tooling that derives the signer from a user-supplied --chainid flag defaulting to 0.
Related errors
- nil chainID
- error decoding contract deployer hex %s: %v
- Could not create random uuid: %v
- key generation: could not read from random source:
- key generation: ecdsa.GenerateKey failed:
AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15).
Data as JSON: /api/errors/6f7910b34800e3ad.
Report an issue: GitHub.