hyperledger/fabric · error

empty nonce

Error message

empty nonce

What it means

The SignatureHeader's Nonce is empty. Fabric requires every endorser transaction to carry a fresh random nonce that, together with the creator identity and txid, prevents replay. An empty nonce means the signature header was not populated properly and the transaction would be invalid on the network.

Source

Thrown at core/tx/endorser/parser.go:141

		Nonce:        txenv.SignatureHeader.Nonce,
	}, nil
}

func (e *EndorserTx) validate() error {
	if e.Epoch != 0 {
		return errors.Errorf("invalid epoch in ChannelHeader. Expected 0, got [%d]", e.Epoch)
	}

	if e.Version != 0 {
		return errors.Errorf("invalid version in ChannelHeader. Expected 0, got [%d]", e.Version)
	}

	if err := ValidateChannelID(e.ChannelID); err != nil {
		return err
	}

	if len(e.Nonce) == 0 {
		return errors.New("empty nonce")
	}

	if len(e.Creator) == 0 {
		return errors.New("empty creator")
	}

	if e.ChaincodeID == nil {
		return errors.New("nil ChaincodeId")
	}

	if e.ChaincodeID.Name == "" {
		return errors.New("empty chaincode name in chaincode id")
	}

	// TODO FAB-16170: check proposal hash

	// TODO FAB-16170: verify that txid matches the one in the header

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Generate a fresh nonce with util.GetRandomNonce() and set SignatureHeader.Nonce when building the transaction.
  2. Ensure each transaction uses a NEW nonce — never reuse or blank it for retried submits.
  3. Verify the code path that serializes the SignatureHeader preserves the nonce bytes.

Example fix

// before
sh := &common.SignatureHeader{Creator: creator} // nonce missing
// after
sh := &common.SignatureHeader{Creator: creator, Nonce: util.GetRandomNonce()}
Defensive patterns

Strategy: validation

Validate before calling

func hasNonce(sh *common.SignatureHeader) bool {
    return len(sh.GetNonce()) > 0
}
// before submit: if !hasNonce(sigHeader) { sigHeader.Nonce = util.GetRandomNonce() }

Type guard

func noncePresent(sh *common.SignatureHeader) bool {
    return sh != nil && len(sh.Nonce) > 0
}

Try / catch

tx, err := parser.UnmarshalEndorserTxAndValidate(env)
if err != nil {
    if strings.Contains(err.Error(), "empty nonce") {
        // signature header built without nonce: regenerate tx with a fresh nonce
        return ErrInvalidHeader
    }
    return err
}

Prevention

When it happens

Trigger: UnmarshalEndorserTxAndValidate is given an envelope whose SignatureHeader.Nonce is a zero-length byte slice — the header was built without generating/util.GetRandomNonce, or the nonce was dropped during assembly.

Common situations: Custom transaction assembly forgetting util.GetRandomNonce(); caching/reusing header structs and overwriting nonce with nil; SDK misconfiguration in the transaction-generation pipeline.

Related errors


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