{"record":{"id":"6f7910b34800e3ad","repo":"ethereum/go-ethereum","slug":"invalid-chainid-v","errorCode":null,"errorMessage":"invalid chainID %v","messagePattern":"invalid chainID (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/types/transaction_signing.go","lineNumber":206,"sourceCode":"}\n\n// txtypeSet is a bitmap for transaction types.\ntype txtypeSet [2]uint64\n\nfunc (v *txtypeSet) set(txType byte) {\n\tv[txType/64] |= 1 << (txType % 64)\n}\n\nfunc (v *txtypeSet) has(txType byte) bool {\n\tif txType >= byte(len(v)*64) {\n\t\treturn false\n\t}\n\treturn v[txType/64]&(1<<(txType%64)) != 0\n}\n\nfunc newModernSigner(chainID *big.Int, fork forks.Fork) Signer {\n\tif chainID == nil || chainID.Sign() <= 0 {\n\t\tpanic(fmt.Sprintf(\"invalid chainID %v\", chainID))\n\t}\n\ts := &modernSigner{\n\t\tchainID: chainID,\n\t}\n\t// configure legacy signer\n\tswitch {\n\tcase fork >= forks.SpuriousDragon:\n\t\ts.legacy = NewEIP155Signer(chainID)\n\tcase fork >= forks.Homestead:\n\t\ts.legacy = HomesteadSigner{}\n\tdefault:\n\t\ts.legacy = FrontierSigner{}\n\t}\n\ts.txtypes.set(LegacyTxType)\n\t// configure tx types\n\tif fork >= forks.Berlin {\n\t\ts.txtypes.set(AccessListTxType)\n\t}","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/ethereum/go-ethereum/blob/6bb0588ad8e7f922e4ad5580f51265a4097af08f/core/types/transaction_signing.go#L188-L224","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsigner := types.LatestSignerForChainID(nil) // panics\n\n// after\nchainID := big.NewInt(1)\nif cfg.ChainID != nil && cfg.ChainID.Sign() > 0 {\n    chainID = cfg.ChainID\n}\nsigner := types.LatestSignerForChainID(chainID)","handlingStrategy":"validation","validationCode":"func validChainID(id *big.Int) bool {\n    return id != nil && id.Sign() > 0\n}\n\n// use before constructing the signer\nif !validChainID(cfg.ChainID) {\n    return fmt.Errorf(\"chain id must be positive, got %v\", cfg.ChainID)\n}\nsigner := types.LatestSignerForChainID(cfg.ChainID)","typeGuard":null,"tryCatchPattern":"Not applicable — validate the chain ID before the call; recovering from this panic would leave you without a valid signer anyway.","preventionTips":["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."],"tags":["signer","chain-id","eip-155","validation","panic"],"backgroundTag":null,"analyzedSha":"6bb0588ad8e7f922e4ad5580f51265a4097af08f","analyzedAt":"2026-08-15T10:06:53.996Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}