{"record":{"id":"6faf339d9a6a6b6e","repo":"hashicorp/nomad","slug":"failed-to-write-data-at-key-s-v","errorCode":null,"errorMessage":"failed to write data at key %s: %v","messagePattern":"failed to write data at key (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/boltdd/boltdd.go","lineNumber":332,"sourceCode":"\tif err := codec.NewEncoder(&buf, structs.MsgpackHandle).Encode(val); err != nil {\n\t\treturn fmt.Errorf(\"failed to encode passed object: %v\", err)\n\t}\n\n\t// Hash for skipping unnecessary writes\n\thashKey := string(key)\n\thashVal := blake2b.Sum256(buf.Bytes())\n\n\t// lastHash value or nil if it hasn't been hashed yet\n\tlastHash := b.bm.getHash(hashKey)\n\n\t// If the hashes are equal, skip the write\n\tif bytes.Equal(hashVal[:], lastHash) {\n\t\treturn nil\n\t}\n\n\t// New value: write it to the underlying boltdb\n\tif err := b.boltBucket.Put(key, buf.Bytes()); err != nil {\n\t\treturn fmt.Errorf(\"failed to write data at key %s: %v\", key, err)\n\t}\n\n\t// New value written, store hash (bucket path map was created above)\n\tb.bm.setHash(hashKey, hashVal[:])\n\n\treturn nil\n\n}\n\n// Get value by key from boltdb or return an ErrNotFound error if key not\n// found.\nfunc (b *Bucket) Get(key []byte, obj interface{}) error {\n\t// Get the raw data from the underlying boltdb\n\tdata := b.boltBucket.Get(key)\n\tif data == nil {\n\t\treturn NotFound(string(key))\n\t}\n","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/boltdd/boltdd.go#L314-L350","documentation":"boltdd.Bucket.Put wraps a failure from the underlying bolt bucket's Put when writing the serialized bytes at the given key. The value encoded fine, but the boltdb transaction rejected the write. Since bolt only allows one write transaction, this usually means the write is happening outside a writable transaction or the DB is in a read-only/invalid state.","triggerScenarios":"Calling Put after the DB was opened read-only (bolt.ErrDatabaseNotOpen / ErrDatabaseReadOnly); calling Put outside the single allowed write transaction (bolt.ErrTxNotWritable) or after that transaction committed/rolled back; key or value exceeding bolt limits; disk full / I/O error while writing the page.","commonSituations":"Concurrent writers racing for bolt's single write lock; calling Put after Close or from a goroutine outside the managed transaction; read-only file system or full disk on the node; snapshot restore running concurrently with writes.","solutions":["Inspect the wrapped %v cause (e.g. ErrTxNotWritable, ErrDatabaseNotOpen) to identify the transaction/state problem.","Ensure all Put calls occur inside the single active write transaction managed by boltdd and before it is committed.","Verify the DB file is writable, the disk is not full, and the DB is not opened with ReadOnly:true.","Check for code paths calling Put after Close or after restore/rollback, and serialize writers behind one goroutine/lock."],"exampleFix":"// before\ngo func() { bucket.Put(key, val) }() // outside write tx / concurrent\n// after\nerr := db.Update(func(tx interface{}) error {\n    return bucket.Put(key, val) // inside managed write transaction\n})","handlingStrategy":"try-catch","validationCode":"// before writing: ensure DB is open and writable\ndb.View() // will fail fast if DB is not open; instead track state:\nif dbClosed || !inWriteTx {\n    return errors.New(\"cannot Put: no active write transaction / db closed\")\n}","typeGuard":null,"tryCatchPattern":"if err := b.Put(key, val); err != nil {\n    var pe *boltdbWriteErr // or inspect wrapped cause\n    if errors.Is(err, bolt.ErrTxNotWritable) || errors.Is(err, bolt.ErrDatabaseNotOpen) {\n        // route write through the single writer goroutine / reopen db\n    }\n    return fmt.Errorf(\"put %q: %w\", key, err)\n}","preventionTips":["Perform all writes inside the single managed write transaction; never call Put from arbitrary goroutines.","Check DB open/ReadOnly state before writing; avoid Put after Close or during restore.","Monitor disk space and file permissions on the data directory.","Serialize writers behind one goroutine or lock to respect bolt's single-writer model."],"tags":["storage","boltdb","write-failure","serialization"],"backgroundTag":"bolt-write-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}