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 ChaincodeActionPayload

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure every element appended to tx.Actions is a fully populated, non-nil TransactionAction
  2. Re-serialize the transaction from a known-good code path (SDK transaction builder)
  3. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/c3c66a846631f521. Report an issue: GitHub.