{"record":{"id":"6c9349fe77fc6430","repo":"AdguardTeam/AdGuardHome","slug":"putting-unit-to-database-w","errorCode":null,"errorMessage":"putting unit to database: %w","messagePattern":"putting unit to database: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/stats/unit.go","lineNumber":359,"sourceCode":"\n// flushUnitToDB puts udb to the database at id.\nfunc (s *StatsCtx) flushUnitToDB(udb *unitDB, tx *bbolt.Tx, id uint32) (err error) {\n\ts.logger.Debug(\"flushing unit\", \"id\", id, \"req_num\", udb.NTotal)\n\n\tbkt, err := tx.CreateBucketIfNotExists(idToUnitName(id))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"creating bucket: %w\", err)\n\t}\n\n\tbuf := &bytes.Buffer{}\n\terr = gob.NewEncoder(buf).Encode(udb)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encoding unit: %w\", err)\n\t}\n\n\terr = bkt.Put([]byte{0}, buf.Bytes())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"putting unit to database: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc convertTopSlice(a []countPair) (m []map[string]uint64) {\n\tm = make([]map[string]uint64, 0, len(a))\n\tfor _, it := range a {\n\t\tm = append(m, map[string]uint64{it.Name: it.Count})\n\t}\n\n\treturn m\n}\n\n// pairsGetter is a signature for topsCollector argument.\ntype pairsGetter func(u *unitDB) (pairs []countPair)\n\n// topsCollector collects statistics about highest values from the given *unitDB","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/stats/unit.go#L341-L377","documentation":"After encoding, putting the unit's bytes into the bbolt bucket failed; wrapped as 'putting unit to database'.","triggerScenarios":"bkt.Put failing due to a read-only transaction, transaction too large (exceeds bbolt/disk limits), or the DB being closed/corrupted during flush.","commonSituations":"Very large stats units (huge transaction), disk full, or races between flush and Close/clear.","solutions":["Reduce the stats data volume or increase available disk/space for the transaction","Verify no concurrent Close/reset while flushing","Batch or trim oversized units before flush"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := s.Close(); err != nil { log.Printf(\"persist failed: %v\", err) }","preventionTips":["Bound per-unit data size","Monitor disk space; enlarge volume for large deployments"],"tags":["stats","database","bbolt"],"backgroundTag":"database-write-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}