{"record":{"id":"a3abb47e450cb5fa","repo":"dgraph-io/badger","slug":"cannot-use-getsequence-in-read-only-mode","errorCode":null,"errorMessage":"Cannot use GetSequence in read-only mode.","messagePattern":"Cannot use GetSequence in read-only mode\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":1432,"sourceCode":"\t\t\treturn err\n\t\t}\n\t\tseq.leased = lease\n\t\treturn nil\n\t})\n}\n\n// GetSequence would initiate a new sequence object, generating it from the stored lease, if\n// available, in the database. Sequence can be used to get a list of monotonically increasing\n// integers. Multiple sequences can be created by providing different keys. Bandwidth sets the\n// size of the lease, determining how many Next() requests can be served from memory.\n//\n// GetSequence is not supported on ManagedDB. Calling this would result in a panic.\nfunc (db *DB) GetSequence(key []byte, bandwidth uint64) (*Sequence, error) {\n\tif db.opt.managedTxns {\n\t\tpanic(\"Cannot use GetSequence with managedDB=true.\")\n\t}\n\tif db.opt.ReadOnly {\n\t\tpanic(\"Cannot use GetSequence in read-only mode.\")\n\t}\n\n\tswitch {\n\tcase len(key) == 0:\n\t\treturn nil, ErrEmptyKey\n\tcase bandwidth == 0:\n\t\treturn nil, ErrZeroBandwidth\n\t}\n\tseq := &Sequence{\n\t\tdb:        db,\n\t\tkey:       key,\n\t\tnext:      0,\n\t\tleased:    0,\n\t\tbandwidth: bandwidth,\n\t}\n\terr := seq.updateLease()\n\treturn seq, err\n}","sourceCodeStart":1414,"sourceCodeEnd":1450,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/db.go#L1414-L1450","documentation":"Returned by DB.GetSequence when the database was opened with read-only options. Sequence leasing requires writing lease records to the value log/SSTables to guarantee monotonically increasing integers, which is impossible without write access, so the read-only mode guard rejects the call before any sequence object is created.","triggerScenarios":"Calling db.GetSequence on a DB opened with badger.ReadOnly option, e.g. opening a shared DB directory as a secondary read-only reader.","commonSituations":"Read-only replicas mounted for inspection; read-only backup/restore tools that also try to allocate IDs; forgotten ReadOnly flag in config.","solutions":["Open the DB without badger.ReadOnly if writes (and sequences) are needed","In read-only deployments, generate sequences elsewhere (a writable DB, a counter service)","Guard the call with a check of db.opt.ReadOnly"],"exampleFix":"// before\nopt.ReadOnly = true\nseq, _ := db.GetSequence([]byte(\"k\"), 100) // panics\n// after\nif !db.opt.ReadOnly {\n    seq, _ = db.GetSequence([]byte(\"k\"), 100)\n} else { id = externalCounter() }","handlingStrategy":"validation","validationCode":"if db.opt.ReadOnly { return errors.New(\"GetSequence unavailable in read-only mode\") }","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if strings.Contains(fmt.Sprint(r), \"read-only\") { /* use external counter */ }\n    }\n}()","preventionTips":["Only call mutation-adjacent APIs (Sequence, DropAll, Flatten) on writable handles","Gate ID generation behind a writable-primary abstraction","Log the ReadOnly flag at startup to catch misconfig early"],"tags":["badger","panic","sequence","read-only"],"backgroundTag":"unsupported-api-in-mode","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"}