hyperledger/fabric · error

signed chaincode deployment spec cannot be nil in a package

Error message

signed chaincode deployment spec cannot be nil in a package

What it means

Within ValidateCC, after confirming the package was initialized, the code checks that the SignedChaincodeDeploymentSpec actually contains a ChaincodeDeploymentSpec. If sDepSpec.ChaincodeDeploymentSpec is nil, the package is structurally invalid — it claims to be a signed deployment spec but carries no deployment payload. This is more specific than the 'uninitialized package' case.

Source

Thrown at core/common/ccprovider/sigcdspackage.go:188

	// compute the id
	hash.Write(scdsdata.CodeHash)
	hash.Write(scdsdata.MetaDataHash)
	hash.Write(scdsdata.SignatureHash)

	id := hash.Sum(nil)

	return b, id, scdsdata, nil
}

// ValidateCC returns error if the chaincode is not found or if its not a
// ChaincodeDeploymentSpec
func (ccpack *SignedCDSPackage) ValidateCC(ccdata *ChaincodeData) error {
	if ccpack.sDepSpec == nil {
		return errors.New("uninitialized package")
	}

	if ccpack.sDepSpec.ChaincodeDeploymentSpec == nil {
		return errors.New("signed chaincode deployment spec cannot be nil in a package")
	}

	if ccpack.depSpec == nil {
		return errors.New("chaincode deployment spec cannot be nil in a package")
	}

	// This is a hack. LSCC expects a specific LSCC error when names are invalid so it
	// has its own validation code. We can't use that error because of import cycles.
	// Unfortunately, we also need to check if what have makes some sort of sense as
	// protobuf will gladly deserialize garbage and there are paths where we assume that
	// a successful unmarshal means everything works but, if it fails, we try to unmarshal
	// into something different.
	if !isPrintable(ccdata.Name) {
		return fmt.Errorf("invalid chaincode name: %q", ccdata.Name)
	}

	if ccdata.Name != ccpack.depSpec.ChaincodeSpec.ChaincodeId.Name || ccdata.Version != ccpack.depSpec.ChaincodeSpec.ChaincodeId.Version {
		return fmt.Errorf("invalid chaincode data %v (%v)", ccdata, ccpack.depSpec.ChaincodeSpec.ChaincodeId)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the package ensuring ChaincodeDeploymentSpec is populated (proto.Marshal of a real ChaincodeDeploymentSpec) before signing.
  2. Validate input bytes by unmarshalling into SignedChaincodeDeploymentSpec and checking ChaincodeDeploymentSpec != nil before calling GetCCPackage.
  3. Fix the producing tool/SDK so it always embeds the deployment spec in the signed wrapper.
  4. Reject untrusted payloads upstream with a clear message instead of letting GetCCPackage report the generic validation failure.

Example fix

// before
scds := &pb.SignedChaincodeDeploymentSpec{InstantiationPolicy: policy}
// after
cdsBytes, _ := proto.Marshal(cds)
scds := &pb.SignedChaincodeDeploymentSpec{ChaincodeDeploymentSpec: cdsBytes, InstantiationPolicy: policy}
Defensive patterns

Strategy: validation

Validate before calling

var scds pb.SignedChaincodeDeploymentSpec
if err := proto.Unmarshal(bytes, &scds); err != nil {
    return err
}
if scds.ChaincodeDeploymentSpec == nil {
    return errors.New("package rejected: embedded ChaincodeDeploymentSpec is nil")
}

Type guard

func hasDeploymentSpec(scds *pb.SignedChaincodeDeploymentSpec) bool {
    return scds != nil && scds.ChaincodeDeploymentSpec != nil && scds.ChaincodeDeploymentSpec.ChaincodeSpec != nil
}

Try / catch

if err := pack.ValidateCC(ccdata); err != nil {
    if strings.Contains(err.Error(), "signed chaincode deployment spec cannot be nil") {
        // regenerate the package with an embedded deployment spec
    }
    return err
}

Prevention

When it happens

Trigger: ValidateCC (via GetCCPackage) is given a package initialized from bytes that decode to a SignedChaincodeDeploymentSpec whose ChaincodeDeploymentSpec field is unset — e.g. a serialized protobuf with only metadata/owner fields populated.

Common situations: Hand-crafted or truncated protobuf payloads in uploads/tests; SDKs serializing the wrapper message without embedding the deployment spec; wrong-field assignment when constructing SignedChaincodeDeploymentSpec programmatically.

Related errors


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