{"record":{"id":"499794d3e93d1e2e","repo":"AdguardTeam/AdGuardHome","slug":"opening-a-transaction-w","errorCode":null,"errorMessage":"opening a transaction: %w","messagePattern":"opening a transaction: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/stats/stats.go","lineNumber":197,"sourceCode":"\t}\n\n\tif s.unitIDGen = newUnitID; conf.UnitID != nil {\n\t\ts.unitIDGen = conf.UnitID\n\t}\n\n\t// TODO(e.burkov):  Move the code below to the Start method.\n\n\terr = s.openDB()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"opening database: %w\", err)\n\t}\n\n\tvar udb *unitDB\n\tid := s.unitIDGen()\n\n\ttx, err := s.db.Load().Begin(true)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"opening a transaction: %w\", err)\n\t}\n\n\tdeleted := s.deleteOldUnits(tx, id-uint32(s.limit.Hours())-1)\n\tudb = s.loadUnitFromDB(tx, id)\n\n\terr = finishTxn(tx, deleted > 0)\n\tif err != nil {\n\t\ts.logger.Error(\"finishing transacation\", slogutil.KeyError, err)\n\t}\n\n\ts.curr = newUnit(id)\n\ts.curr.deserialize(udb)\n\n\ts.logger.Debug(\"initialized\")\n\n\treturn s, nil\n}\n","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/stats/stats.go#L179-L215","documentation":"During stats.New, a write transaction could not be started on the bbolt database; the Begin(true) error is wrapped as 'opening a transaction'.","triggerScenarios":"stats.New with a database that is locked, already in use by another process, closed, or on a full/read-only filesystem when Begin(true) is attempted.","commonSituations":"Concurrent processes opening the same bbolt file (bbolt takes an exclusive file lock), disk full, or the file being closed by another goroutine during initialization.","solutions":["Ensure only one process opens the stats DB at a time","Check disk space and filesystem permissions","If it persists, delete the stats DB to reinitialize (losing history)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if _, err := os.Stat(dbPath); errors.Is(err, fs.ErrNotExist) { /* fresh start ok */ } else if err != nil { return err }","typeGuard":null,"tryCatchPattern":"if _, err := stats.New(conf); err != nil { if strings.Contains(err.Error(), \"transaction\") { time.Sleep(time.Second); retry() } }","preventionTips":["Use a file lock to enforce single-writer","Avoid sharing the stats DB across processes"],"tags":["stats","database","bbolt","locking"],"backgroundTag":"database-transaction-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}