{"record":{"id":"bf4f09a318099600","repo":"ethereum/go-ethereum","slug":"not-implemented-bf4f09","errorCode":null,"errorMessage":"not implemented","messagePattern":"not implemented","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"triedb/hashdb/database.go","lineNumber":532,"sourceCode":"\t\tc.db.dirties[node.flushPrev].flushNext = node.flushNext\n\t\tc.db.dirties[node.flushNext].flushPrev = node.flushPrev\n\t}\n\t// Remove the node from the dirty cache\n\tdelete(c.db.dirties, hash)\n\tc.db.dirtiesSize -= common.StorageSize(common.HashLength + len(node.node))\n\tif node.external != nil {\n\t\tc.db.childrenSize -= common.StorageSize(len(node.external) * common.HashLength)\n\t}\n\t// Move the flushed node into the clean cache to prevent insta-reloads\n\tif c.db.cleans != nil {\n\t\tc.db.cleans.Set(hash[:], rlp)\n\t\tmemcacheCleanWriteMeter.Mark(int64(len(rlp)))\n\t}\n\treturn nil\n}\n\nfunc (c *cleaner) Delete(key []byte) error {\n\tpanic(\"not implemented\")\n}\n\n// Update inserts the dirty nodes in provided nodeset into database and link the\n// account trie with multiple storage tries if necessary.\nfunc (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet) error {\n\t// Ensure the parent state is present and signal a warning if not.\n\tif parent != types.EmptyRootHash {\n\t\tif blob, _ := db.node(parent); len(blob) == 0 {\n\t\t\tlog.Error(\"parent state is not present\")\n\t\t}\n\t}\n\tdb.lock.Lock()\n\tdefer db.lock.Unlock()\n\n\t// Insert dirty nodes into the database. In the same tree, it must be\n\t// ensured that children are inserted first, then parent so that children\n\t// can be linked with their parent correctly.\n\t//","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/ethereum/go-ethereum/blob/6bb0588ad8e7f922e4ad5580f51265a4097af08f/triedb/hashdb/database.go#L514-L550","documentation":"The cleaner type wraps the hash database's node cache so it can be iterated as an ethdb.KeyValueReader-ish interface, but the clean cache is a pure read cache backed by disk; deleting individual keys through it is meaningless (disk is the source of truth). Delete therefore panics to signal an unsupported operation rather than silently doing nothing.","triggerScenarios":"Calling Delete on the cleaner wrapper exposed by Database (hashdb) — in practice this happens when generic code treats the cache as a general KeyValueStore and invokes delete/compaction paths on it.","commonSituations":"Fork code that runs compaction (DeleteRange/Delete) against every database handle it can find; accidental reuse of the iterator/cache handle beyond its intended read-only scope; upstream refactors that widened an interface the cleaner implements.","solutions":["Audit the call chain that reaches cleaner.Delete and stop routing write operations to the clean cache","Perform deletions on the real backing store (freezer/LightPeerDatabase), not the cache wrapper","If fork semantics genuinely require it, implement Delete as a cache eviction (c.db.cleans.Set(hash, nil) or equivalent) instead of panicking"],"exampleFix":"// before\n// generic compaction walking all \"databases\"\nfor _, db := range handles { db.Delete(key) } // panics on cleaner\n\n// after\nfor _, db := range handles {\n    if _, readOnly := db.(*hashdb.cleaner); readOnly { continue }\n    db.Delete(key)\n}","handlingStrategy":"validation","validationCode":"// Gate cache-backed handles out of write paths\nfunc isReadOnlyCache(db ethdb.Database) bool {\n    return strings.Contains(fmt.Sprintf(\"%T\", db), \"cleaner\")\n}\nif !isReadOnlyCache(target) { target.Delete(key) }","typeGuard":"type deletable interface{ Delete([]byte) error }\nfunc canDelete(db ethdb.Database) bool {\n    if _, ok := db.(deletable); !ok { return false }\n    return !isReadOnlyCache(db)\n}","tryCatchPattern":null,"preventionTips":["Pass the underlying LightPeerDatabase/freezer to deletion logic, never cache wrappers","Keep the cleaner unexported so it cannot leak into consumer signatures","In fork code, consider not implementing the delete-bearing interface on caches at all"],"tags":["triedb","hashdb","cache","misuse","panic"],"backgroundTag":null,"analyzedSha":"6bb0588ad8e7f922e4ad5580f51265a4097af08f","analyzedAt":"2026-08-15T10:06:53.996Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}