{"record":{"id":"d0937039762b80de","repo":"hyperledger/fabric","slug":"id-cannot-be-nil-if-buf-is-not-nil-d09370","errorCode":null,"errorMessage":"id cannot be nil if buf is not nil","messagePattern":"id cannot be nil if buf is not nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/common/ccprovider/sigcdspackage.go","lineNumber":286,"sourceCode":"\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif _, err = ccpack.InitFromBuffer(buf); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn ccpack.buf, ccpack.depSpec, nil\n}\n\n// PutChaincodeToFS - serializes chaincode to a package on the file system\nfunc (ccpack *SignedCDSPackage) PutChaincodeToFS() error {\n\tif ccpack.buf == nil {\n\t\treturn errors.New(\"uninitialized package\")\n\t}\n\n\tif ccpack.id == nil {\n\t\treturn errors.New(\"id cannot be nil if buf is not nil\")\n\t}\n\n\tif ccpack.sDepSpec == nil || ccpack.depSpec == nil {\n\t\treturn errors.New(\"depspec cannot be nil if buf is not nil\")\n\t}\n\n\tif ccpack.env == nil {\n\t\treturn errors.New(\"env cannot be nil if buf and depspec are not nil\")\n\t}\n\n\tif ccpack.data == nil {\n\t\treturn errors.New(\"nil data\")\n\t}\n\n\tif ccpack.datab == nil {\n\t\treturn errors.New(\"nil data bytes\")\n\t}\n","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/common/ccprovider/sigcdspackage.go#L268-L304","documentation":"PutChaincodeToFS also requires ccpack.id to be non-nil whenever buf is set. The id is the package hash computed by getCDSData during initialization; nil means the initialization did not compute the package identity. This guard prevents writing packages whose hash was never derived.","triggerScenarios":"PutChaincodeToFS on a package where buf was set but id was never computed — e.g. fields populated manually or an init path that skipped getCDSData.","commonSituations":"Hand-assembling SignedCDSPackage structs in custom tooling; partial initialization after an earlier error was swallowed; fabric version changes altering the init flow.","solutions":["Initialize the package through the standard path (GetCCPackage / InitFromBuffer) so id is computed via getCDSData","Do not set ccpack.buf manually without also computing id","Fix error handling so failed initialization never reaches the write step"],"exampleFix":"// before\nccpack.buf = buf // id left nil\nccpack.PutChaincodeToFS()\n// after\nccpack := &SignedCDSPackage{}\nccpack.InitFromBuffer(buf) // computes id via getCDSData\nccpack.PutChaincodeToFS()","handlingStrategy":"type-guard","validationCode":"func hasComputedID(buf []byte) bool {\n    // id must come from a successful init/getCDSData, not manual assignment\n    return len(buf) > 0 // pre-check; real id check requires init\n}\n// Prefer: init then check GetId() error before persisting.","typeGuard":"func fullyInit(ccpack *ccprovider.SignedCDSPackage) bool {\n    _, _, err := ccpack.GetDepSpec()\n    return err == nil // GetDepSpec errors when id/buf/depSpec are unset\n}","tryCatchPattern":"if _, err := ccpack.InitFromBuffer(buf); err != nil {\n    return err // ensures id computed via getCDSData\n}\nif err := ccpack.PutChaincodeToFS(); err != nil {\n    if strings.Contains(err.Error(), \"id cannot be nil\") { return errors.New(\"package id never computed; use standard init\") }\n    return err\n}","preventionTips":["Never assign ccpack.buf directly; always go through InitFromBuffer","Let getCDSData compute the package id during init","Add an init-then-persist invariant check in custom install tooling"],"tags":["chaincode","fabric","lifecycle","initialization"],"backgroundTag":"uninitialized-object","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}