hyperledger/fabric · error

ChaincodeHeaderExtension.ChaincodeId is nil

Error message

ChaincodeHeaderExtension.ChaincodeId is nil

What it means

UnpackProposal decodes the header extension into a ChaincodeHeaderExtension via protoutil.UnmarshalChaincodeHeaderExtension. Even if unmarshaling succeeds, the resulting ChaincodeId field can be nil (e.g. extension bytes only carried a payload hash); a proposal without a chaincode ID cannot be routed, so it is rejected.

Source

Thrown at core/endorser/msgvalidation.go:69

	}

	chdr, err := protoutil.UnmarshalChannelHeader(hdr.ChannelHeader)
	if err != nil {
		return nil, err
	}

	shdr, err := protoutil.UnmarshalSignatureHeader(hdr.SignatureHeader)
	if err != nil {
		return nil, err
	}

	chaincodeHdrExt, err := protoutil.UnmarshalChaincodeHeaderExtension(chdr.Extension)
	if err != nil {
		return nil, err
	}

	if chaincodeHdrExt.ChaincodeId == nil {
		return nil, errors.Errorf("ChaincodeHeaderExtension.ChaincodeId is nil")
	}

	if chaincodeHdrExt.ChaincodeId.Name == "" {
		return nil, errors.Errorf("ChaincodeHeaderExtension.ChaincodeId.Name is empty")
	}

	cpp, err := protoutil.UnmarshalChaincodeProposalPayload(prop.Payload)
	if err != nil {
		return nil, err
	}

	cis, err := protoutil.UnmarshalChaincodeInvocationSpec(cpp.Input)
	if err != nil {
		return nil, err
	}

	if cis.ChaincodeSpec == nil {
		return nil, errors.Errorf("chaincode invocation spec did not contain chaincode spec")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Build the proposal with the current SDK/protoutil so the header extension includes ChaincodeId with name and version
  2. Regenerate the proposal if it was created by older tooling
  3. Validate the decoded ChaincodeHeaderExtension before submitting

Example fix

// before
ext := &pb.ChaincodeHeaderExtension{PayloadVisibility: []byte("hash")} // no ChaincodeId
// after
ext := &pb.ChaincodeHeaderExtension{ChaincodeId: &pb.ChaincodeID{Name: "mycc", Version: "1.0"}}
Defensive patterns

Strategy: validation

Validate before calling

ext := &pb.ChaincodeHeaderExtension{ChaincodeId: &pb.ChaincodeID{Name: ccName, Version: ccVer}}
if ext.ChaincodeId == nil || ext.ChaincodeId.Name == "" {
    return errors.New("proposal extension must set ChaincodeId.Name")
}

Type guard

func hasChaincodeId(ext *pb.ChaincodeHeaderExtension) bool {
    return ext != nil && ext.ChaincodeId != nil
}

Prevention

When it happens

Trigger: Submitting a proposal whose ChannelHeader.Extension unmarshals to a ChaincodeHeaderExtension with ChaincodeId == nil — typically an old-style or malformed proposal extension containing only the payload hash.

Common situations: Clients built against Fabric 1.0-era message formats where the extension omitted ChaincodeId; hand-crafted proposals in tests/tools; corrupted or truncated header extensions.

Related errors


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