hyperledger/fabric · error

nil data bytes

Error message

nil data bytes

What it means

ccpack.datab is the serialized bytes of the ChaincodeData (data marshaled to protobuf). PutChaincodeToFS checks it last before writing: buf/id/depSpec/data all present but datab nil means the final marshal step never ran, so the on-disk package would be incomplete and the write is refused.

Source

Thrown at core/common/ccprovider/cdspackage.go:244

func (ccpack *CDSPackage) PutChaincodeToFS() error {
	if ccpack.buf == nil {
		return errors.New("uninitialized package")
	}

	if ccpack.id == nil {
		return errors.New("id cannot be nil if buf is not nil")
	}

	if ccpack.depSpec == nil {
		return errors.New("depspec cannot be nil if buf is not nil")
	}

	if ccpack.data == nil {
		return errors.New("nil data")
	}

	if ccpack.datab == nil {
		return errors.New("nil data bytes")
	}

	ccname := ccpack.depSpec.ChaincodeSpec.ChaincodeId.Name
	ccversion := ccpack.depSpec.ChaincodeSpec.ChaincodeId.Version

	// return error if chaincode exists
	path := fmt.Sprintf("%s/%s.%s", chaincodeInstallPath, ccname, ccversion)
	if _, err := os.Stat(path); err == nil {
		return fmt.Errorf("chaincode %s exists", path)
	}

	if err := os.WriteFile(path, ccpack.buf, 0o644); err != nil {
		return err
	}

	return nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Initialize via InitFromBuffer/InitFromPath, which marshal ChaincodeData into datab, then call PutChaincodeToFS.
  2. If manual, marshal the data yourself: datab, err := proto.Marshal(ccpack.data); check err and assign ccpack.datab before writing.
  3. Stop hand-assembling CDSPackage and route through ccprovider.PutChaincode / processCDS which guarantee full population.

Example fix

// before
ccpack.data = ccdata // datab never marshaled
ccpack.PutChaincodeToFS()

// after
datab, err := proto.Marshal(ccdata)
if err != nil {
    return err
}
ccpack.datab = datab
ccpack.PutChaincodeToFS()
Defensive patterns

Strategy: validation

Validate before calling

if ccpack.buf != nil && ccpack.datab == nil {
    return errors.New("ChaincodeData bytes missing: data must be marshaled before PutChaincodeToFS")
}

Type guard

func hasDataBytes(p *ccprovider.CDSPackage) bool {
    return p != nil && p.buf != nil && p.datab != nil
}

Try / catch

if err := ccpack.PutChaincodeToFS(); err != nil {
    if err.Error() == "nil data bytes" {
        return fmt.Errorf("package serialization incomplete: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: A CDSPackage populated through custom code that set data but never serialized it to datab (proto.Marshal step in InitFromBuffer/PutChaincodeDepSpec skipped or its error ignored).

Common situations: Reimplementing package initialization in forked code and missing the datab = proto.Marshal(data) step; a marshal failure swallowed earlier; deep-copying a package and dropping the bytes field; test fixtures missing one field.

Related errors


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