hyperledger/fabric · error
nil action
Error message
nil action
What it means
Inside the loop over tx.Actions, validateEndorserTransaction guards against a nil TransactionAction element. A nil entry cannot yield a SignatureHeader or ChaincodeAction, so validation aborts early with this error.
Source
Thrown at core/common/validation/msgvalidation.go:198
if tx == nil {
return errors.New("nil transaction")
}
// TODO: validate tx.Version
// TODO: validate ChaincodeHeaderExtension
// hlf version 1 only supports a single action per transaction
if len(tx.Actions) != 1 {
return errors.Errorf("only one action per transaction is supported, tx contains %d", len(tx.Actions))
}
putilsLogger.Debugf("validateEndorserTransaction info: there are %d actions", len(tx.Actions))
for _, act := range tx.Actions {
// check for nil argument
if act == nil {
return errors.New("nil action")
}
// if the type is ENDORSER_TRANSACTION we unmarshal a SignatureHeader
sHdr, err := protoutil.UnmarshalSignatureHeader(act.Header)
if err != nil {
return err
}
// validate the SignatureHeader - here we actually only
// care about the nonce since the creator is in the outer header
err = validateSignatureHeader(sHdr)
if err != nil {
return err
}
putilsLogger.Debugf("validateEndorserTransaction info: signature header is valid")
// if the type is ENDORSER_TRANSACTION we unmarshal a ChaincodeActionPayloadView on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure every element appended to tx.Actions is a fully populated, non-nil TransactionAction
- Re-serialize the transaction from a known-good code path (SDK transaction builder)
- Add a pre-submit loop asserting no nil actions before marshalling
Example fix
// before
actions := make([]*common.TransactionAction, 2) // [nil, nil]
// after
actions := []*common.TransactionAction{action1, action2} Defensive patterns
Strategy: validation
Validate before calling
for i, act := range tx.Actions {
if act == nil { return fmt.Errorf("action %d is nil", i) }
} Type guard
func allActionsPresent(tx *common.Transaction) bool {
for _, a := range tx.Actions { if a == nil { return false } }
return len(tx.Actions) > 0
} Prevention
- Use composite literals to fill slices instead of make() without assignment
- Validate tx structure before marshalling
- Prefer SDK transaction builders over manual proto assembly
When it happens
Trigger: ValidateTransaction on a Transaction whose Actions slice contains a nil element (allocated slice with empty slot); TestInvocationsBadArgs covers it directly.
Common situations: Manual protobuf construction (make([]*common.TransactionAction, 1) without assignment), partial deserialization, or client code that appends a placeholder action it never fills in.
Related errors
- error unmarshalling ChaincodeHeaderExtension
- nil ChaincodeId in header extension
- nil ChaincodeId in ChaincodeAction
- invalid chaincode ID
- inconsistent ccid info (%s/%s)
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c3c66a846631f521.
Report an issue: GitHub.