{"record":{"id":"702fe09394ab4274","repo":"hyperledger/fabric","slug":"nil-value-not-allowed-instead-call-delete-funct","errorCode":null,"errorMessage":"Nil value not allowed. Instead call 'Delete' function","messagePattern":"Nil value not allowed\\. Instead call 'Delete' function","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/txmgmt/statedb/statedb.go","lineNumber":198,"sourceCode":"\t\treturn nil\n\t}\n\tvv, ok := nsUpdates.M[key]\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn vv\n}\n\n// Put adds a key with value only. The metadata is assumed to be nil\nfunc (batch *UpdateBatch) Put(ns string, key string, value []byte, version *version.Height) {\n\tbatch.PutValAndMetadata(ns, key, value, nil, version)\n}\n\n// PutValAndMetadata adds a key with value and metadata\n// TODO introducing a new function to limit the refactoring. Later in a separate CR, the 'Put' function above should be removed\nfunc (batch *UpdateBatch) PutValAndMetadata(ns string, key string, value []byte, metadata []byte, version *version.Height) {\n\tif value == nil {\n\t\tpanic(\"Nil value not allowed. Instead call 'Delete' function\")\n\t}\n\tbatch.Update(ns, key, &VersionedValue{value, metadata, version})\n}\n\n// Delete deletes a Key and associated value\nfunc (batch *UpdateBatch) Delete(ns string, key string, version *version.Height) {\n\tbatch.Update(ns, key, &VersionedValue{nil, nil, version})\n}\n\n// Exists checks whether the given key exists in the batch\nfunc (batch *UpdateBatch) Exists(ns string, key string) bool {\n\tnsUpdates, ok := batch.Updates[ns]\n\tif !ok {\n\t\treturn false\n\t}\n\t_, ok = nsUpdates.M[key]\n\treturn ok\n}","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statedb.go#L180-L216","documentation":"UpdateBatch.PutValAndMetadata panics if value is nil. A nil value in an update batch is ambiguous with deletion; the API contract requires explicit Delete calls to remove keys, keeping writes and deletes distinguishable in the redo log and state DB.","triggerScenarios":"Calling PutValAndMetadata (or constructing an UpdateBatch entry via Put) with a nil []byte value during batch assembly — seen in redo-record construction and various statedb/txmgr tests that exercise value+metadata writes.","commonSituations":"Tooling that mirrors GetState results into a batch where the key was missing (GetState returns nil); code that confuses empty value []byte{} (allowed) with nil (not allowed); redo logger replay of malformed records.","solutions":["Use batch.Delete(ns, key, version) instead when the intent is to remove the key.","Pass an empty non-nil slice ([]byte{}) if an empty value is intended.","Guard the caller: if value == nil, route to Delete before adding to the batch.","Fix the upstream producer (e.g. redo record deserialization) that yielded a nil value."],"exampleFix":"// before\nif value == nil { batch.PutValAndMetadata(ns, key, value, md, ver) }\n// after\nif value == nil {\n  batch.Delete(ns, key, ver)\n} else {\n  batch.PutValAndMetadata(ns, key, value, md, ver)\n}","handlingStrategy":"type-guard","validationCode":"if value == nil {\n  batch.Delete(ns, key, version)\n} else {\n  batch.PutValAndMetadata(ns, key, value, metadata, version)\n}","typeGuard":"func isWritableValue(v []byte) bool { return v != nil }","tryCatchPattern":"// panic-based, so guard before calling:\nif value != nil {\n  batch.PutValAndMetadata(ns, key, value, metadata, version)\n}","preventionTips":["Remember nil and empty []byte{} are semantically different: nil=delete signal, []byte{}=empty write","Never feed GetState results directly into Put without a nil check","Audit batch-building code for paths that propagate nil values"],"tags":["panic","statedb","update-batch","ledger"],"backgroundTag":"nil-value-not-allowed","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"}