{"record":{"id":"a625a8b9f43c731b","repo":"dgraph-io/badger","slug":"cannot-ban-namespace-in-read-only-mode","errorCode":null,"errorMessage":"Cannot ban namespace in read-only mode.","messagePattern":"Cannot ban namespace in read-only mode\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":1956,"sourceCode":"\tif db.opt.NamespaceOffset < 0 {\n\t\treturn nil\n\t}\n\tif len(key) <= db.opt.NamespaceOffset+8 {\n\t\treturn nil\n\t}\n\tif db.bannedNamespaces.has(y.BytesToU64(key[db.opt.NamespaceOffset:])) {\n\t\treturn ErrBannedKey\n\t}\n\treturn nil\n}\n\n// BanNamespace bans a namespace. Read/write to keys belonging to any of such namespace is denied.\nfunc (db *DB) BanNamespace(ns uint64) error {\n\tif db.opt.NamespaceOffset < 0 {\n\t\treturn ErrNamespaceMode\n\t}\n\tif db.opt.ReadOnly {\n\t\tpanic(\"Cannot ban namespace in read-only mode.\")\n\t}\n\tdb.opt.Infof(\"Banning namespace: %d\", ns)\n\t// First set the banned namespaces in DB and then update the in-memory structure.\n\tkey := y.KeyWithTs(append(bannedNsKey, y.U64ToBytes(ns)...), 1)\n\tentry := []*Entry{{\n\t\tKey:   key,\n\t\tValue: nil,\n\t}}\n\treq, err := db.sendToWriteCh(entry)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := req.Wait(); err != nil {\n\t\treturn err\n\t}\n\tdb.bannedNamespaces.add(ns)\n\treturn nil\n}","sourceCodeStart":1938,"sourceCodeEnd":1974,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/db.go#L1938-L1974","documentation":"BanNamespace panics when the DB is opened in read-only mode. Banning a namespace writes a marker entry (under bannedNsKey) to the database, which requires write access; read-only handles cannot perform that write, so the library panics to prevent an invalid state.","triggerScenarios":"Calling db.BanNamespace(ns) on a DB opened with badger.Options.ReadOnly = true. Note it also panics-free returns ErrNamespaceMode if NamespaceOffset < 0 — the read-only panic is hit only when namespace mode is configured.","commonSituations":"Multi-tenant apps where a reader replica instance is asked to ban a tenant; a shared DB wrapper opened read-only for queries but also wired to admin handlers; forgetting that namespace bans are persisted writes, not in-memory-only flags.","solutions":["Open a writable DB instance to call BanNamespace","Guard the call: skip or return an error when the DB options are read-only","Persist banned namespaces through your own config store and apply them only on writable instances"],"exampleFix":"// before\nif err := roDB.BanNamespace(ns); err != nil { ... }\n\n// after\nif !roDB.IsClosed() && !opts.ReadOnly {\n    if err := db.BanNamespace(ns); err != nil { ... }\n}","handlingStrategy":"validation","validationCode":"if opts.ReadOnly { return errors.New(\"BanNamespace requires a writable DB\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Expose admin operations only on writable DB instances","Check opt.ReadOnly before invoking namespace admin APIs","Remember BanNamespace persists state — it can never be read-only"],"tags":["badger","read-only","panic","namespace"],"backgroundTag":"read-only-mode-violation","analyzedSha":"2a001d466f6b71a917319a1db41f99860e16e269","analyzedAt":"2026-09-05T13:00:02.264Z","contentChangedAt":"2026-09-05T13:00:02.264Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}