{"record":{"id":"c73b49edec411cc6","repo":"ethereum/go-ethereum","slug":"nil-chainid","errorCode":null,"errorMessage":"nil chainID","messagePattern":"nil chainID","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"accounts/abi/bind/v2/auth.go","lineNumber":40,"sourceCode":"\t\"errors\"\n\t\"math/big\"\n\n\t\"github.com/ethereum/go-ethereum/accounts\"\n\t\"github.com/ethereum/go-ethereum/accounts/external\"\n\t\"github.com/ethereum/go-ethereum/accounts/keystore\"\n\t\"github.com/ethereum/go-ethereum/common\"\n\t\"github.com/ethereum/go-ethereum/core/types\"\n\t\"github.com/ethereum/go-ethereum/crypto\"\n)\n\n// ErrNotAuthorized is returned when an account is not properly unlocked.\nvar ErrNotAuthorized = errors.New(\"not authorized to sign this account\")\n\n// NewKeyStoreTransactor is a utility method to easily create a transaction signer from\n// a decrypted key from a keystore.\nfunc NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) *TransactOpts {\n\tif chainID == nil {\n\t\tpanic(\"nil chainID\")\n\t}\n\tsigner := types.LatestSignerForChainID(chainID)\n\treturn &TransactOpts{\n\t\tFrom: account.Address,\n\t\tSigner: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {\n\t\t\tif address != account.Address {\n\t\t\t\treturn nil, ErrNotAuthorized\n\t\t\t}\n\t\t\tsignature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treturn tx.WithSignature(signer, signature)\n\t\t},\n\t\tContext: context.Background(),\n\t}\n}\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/ethereum/go-ethereum/blob/6bb0588ad8e7f922e4ad5580f51265a4097af08f/accounts/abi/bind/v2/auth.go#L22-L58","documentation":"NewKeyStoreTransactor in accounts/abi/bind/v2 builds a transaction signer from a keystore account and requires a non-nil EIP-155 chainID to select the latest signer for that chain. Passing a nil *big.Int would later dereference nil inside the signer; the constructor fails fast with panic(\"nil chainID\") instead.","triggerScenarios":"Calling bind v2's NewKeyStoreTransactor(keystore, account, nil) — e.g. the chain ID variable was never assigned, a config field left empty, or a nil was propagated from a lookup like ethclient.ChainID() error path where the returned value was used despite an error.","commonSituations":"Migrating from the old bind API (where chainID was inside bind.TransactOpts) to v2 and forgetting the new parameter; using a helper that returns (chainID, err) and ignoring err, leaving chainID nil; tests that construct transactors without setting the chain.","solutions":["Fetch the chain ID from the connected client and check the error: cid, err := client.ChainID(ctx); if err != nil return err.","Pass an explicit big.NewInt(<your chain id>) for known private/dev chains (e.g. 1337, 1).","If nil can reach this call by design, guard before calling and return a proper error instead of panicking."],"exampleFix":"// before\nopts := bind.NewKeyStoreTransactor(ks, acct, nil) // panics\n\n// after\nchainID, err := client.ChainID(ctx)\nif err != nil { return err }\nopts := bind.NewKeyStoreTransactor(ks, acct, chainID)","handlingStrategy":"validation","validationCode":"func mustChainID(ctx context.Context, client *ethclient.Client) (*big.Int, error) {\n\tcid, err := client.ChainID(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"fetching chain id: %w\", err)\n\t}\n\treturn cid, nil\n}\n// opts, err := mustChainID(ctx, client); if err == nil { bind.NewKeyStoreTransactor(ks, acct, cid) }","typeGuard":"func hasChainID(cid *big.Int) bool { return cid != nil && cid.Sign() >= 0 }","tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tif msg, _ := r.(string); strings.Contains(msg, \"nil chainID\") {\n\t\t\treturn nil, errors.New(\"chain id missing: connect client and fetch ChainID first\")\n\t\t}\n\t\tpanic(r)\n\t}\n}()","preventionTips":["Always pair client.ChainID with its error check.","For known chains, pass a constant big.NewInt(chainID).","Wrap transactor constructors in your own helper that validates first."],"tags":["go-ethereum","abi-bind","chainid","panic"],"backgroundTag":null,"analyzedSha":"6bb0588ad8e7f922e4ad5580f51265a4097af08f","analyzedAt":"2026-08-15T10:06:53.996Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}