{"record":{"id":"ec43d058cd6e0523","repo":"dgraph-io/badger","slug":"wb-err-w-err-w","errorCode":null,"errorMessage":"wb.err: %w err: %w","messagePattern":"wb\\.err: %w err: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"batch.go","lineNumber":224,"sourceCode":"\treturn wb.Error()\n}\n\n// Flush must be called at the end to ensure that any pending writes get committed to Badger. Flush\n// returns any error stored by WriteBatch.\nfunc (wb *WriteBatch) Flush() error {\n\twb.Lock()\n\terr := wb.commit()\n\tif err != nil {\n\t\twb.Unlock()\n\t\treturn err\n\t}\n\twb.finished = true\n\twb.txn.Discard()\n\twb.Unlock()\n\n\tif err := wb.throttle.Finish(); err != nil {\n\t\tif wb.Error() != nil {\n\t\t\treturn fmt.Errorf(\"wb.err: %w err: %w\", wb.Error(), err)\n\t\t}\n\t\treturn err\n\t}\n\n\treturn wb.Error()\n}\n\n// Error returns any errors encountered so far. No commits would be run once an error is detected.\nfunc (wb *WriteBatch) Error() error {\n\t// If the interface conversion fails, the err will be nil.\n\terr, _ := wb.err.Load().(error)\n\treturn err\n}\n","sourceCodeStart":206,"sourceCodeEnd":238,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/batch.go#L206-L238","documentation":"WriteBatch.Flush waits for all async batch commits to finish (via throttle.Finish) and then reports accumulated errors. If both the throttled commit returned an error AND earlier SetEntry calls already recorded an error in the batch, Flush wraps both with \"wb.err: %w err: %w\" so neither failure is lost.","triggerScenarios":"One or more SetEntry calls failed earlier (e.g. ErrTxnTooBig, key too large) AND throttle.Finish also returned an error (e.g. a commit failed, ErrDBClosed) when Flush drained the queue.","commonSituations":"Closing the DB while a WriteBatch is still flushing; oversized entries inflating batch past max size; disk full or IO errors during async commits.","solutions":["Inspect both wrapped errors with errors.Is/Unwrap to find the root cause (e.g. ErrDBClosed, ErrTxnTooBig)","Call wb.Cancel() on error paths before closing the DB so pending writes don't fail mid-flush","Check wb.Error() after each SetEntry loop iteration to fail fast before Flush"],"exampleFix":"// before\nif err := wb.Flush(); err != nil { return err }\n// after\nif err := wb.Flush(); err != nil {\n    if errors.Is(err, badger.ErrDBClosed) { /* DB closed during flush */ }\n    log.Printf(\"flush failed: %v\", err)\n    return err\n}","handlingStrategy":"try-catch","validationCode":"if err := wb.Error(); err != nil { wb.Cancel(); return err } // before Flush\nif db.IsClosed() { return badger.ErrDBClosed }","typeGuard":null,"tryCatchPattern":"if err := wb.Flush(); err != nil {\n    var unwrapped error\n    for e := err; e != nil; unwrapped, e = e, errors.Unwrap(e) { log.Printf(\"cause: %v\", unwrapped) }\n    return err\n}","preventionTips":["Call wb.Cancel() on early-exit paths instead of abandoning the batch","Close the DB only after all WriteBatch Flush calls complete","Check db.IsClosed() before flushing during shutdown"],"tags":["error","write-batch","async","error-wrapping","flush"],"backgroundTag":"write-batch-flush-error","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"}