hashicorp/nomad · warning
Allocation bucket doesn't exist and transaction is not writa
Error message
Allocation bucket doesn't exist and transaction is not writable
What it means
Thrown by getAllocationBucket when the per-allocation child bucket for allocID is missing under the allocations bucket and the transaction is read-only. In a writable tx the bucket would be auto-created with CreateBucket, but reads cannot mutate the tree, so the lookup fails fast. Note the singular 'Allocation' distinguishes it from the root 'Allocations' bucket error.
Source
Thrown at client/state/db_bolt.go:799
// Retrieve the root allocations bucket
allocations := tx.Bucket(allocationsBucketName)
if allocations == nil {
if !w {
return nil, fmt.Errorf("Allocations bucket doesn't exist and transaction is not writable")
}
allocations, err = tx.CreateBucketIfNotExists(allocationsBucketName)
if err != nil {
return nil, err
}
}
// Retrieve the specific allocations bucket
key := []byte(allocID)
alloc := allocations.Bucket(key)
if alloc == nil {
if !w {
return nil, fmt.Errorf("Allocation bucket doesn't exist and transaction is not writable")
}
alloc, err = allocations.CreateBucket(key)
if err != nil {
return nil, err
}
}
return alloc, nil
}
// getTaskBucket returns the bucket used to persist state about a
// particular task. If the root allocation bucket, the specific
// allocation or task bucket doesn't exist, they will be created as long as the
// transaction is writable.
func getTaskBucket(tx *boltdd.Tx, allocID, taskName string) (*boltdd.Bucket, error) {
alloc, err := getAllocationBucket(tx, allocID)
if err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Check whether the alloc bucket was deleted (e.g. by GC) and treat the error as 'alloc state absent'
- Use a writable Update transaction if the caller should create the alloc bucket
- Reconcile allocID against the client's tracked allocations; stale IDs will never have buckets
- Inspect the bolt DB (boltdd/bbolt CLI) to confirm which alloc buckets exist
Example fix
// before
allocState, err := db.GetAllocState(tx, allocID)
if err != nil {
return err
}
// after: tolerate missing read-only bucket as absent state
allocState, err := db.GetAllocState(tx, allocID)
if err != nil {
if strings.Contains(err.Error(), "Allocation bucket doesn't exist") {
return nil // alloc state not persisted; treat as absent
}
return err
} Defensive patterns
Strategy: type-guard
Validate before calling
exists, err := allocBucketExists(db, allocID)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("no persisted state for alloc %s", allocID)
} Type guard
func isMissingAllocBucketErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "Allocation bucket doesn't exist")
} Try / catch
allocState, err := db.GetAllocState(tx, allocID)
if isMissingAllocBucketErr(err) {
return nil // state absent (never persisted or GC'd)
}
if err != nil {
return err
} Prevention
- Track alloc lifecycles so reads never race bucket GC/deletion
- Verify allocID validity before querying state
- Rebuild/re-restore missing alloc buckets only in Update transactions
- Audit backup/restore flows to confirm alloc buckets are preserved
When it happens
Trigger: Calling GetAllocation/GetAllocState/db writes routed through a View() for an allocID whose bucket was never created (e.g. never restored after restart, deleted by DeleteAllocationBucket, or wiped state dir).
Common situations: Client restored from a backup missing that alloc's bucket; alloc state read after bucket deletion during GC; querying stale allocIDs against a rebuilt state DB; concurrent GC removing the alloc bucket while a read transaction runs.
Related errors
- Allocations bucket doesn't exist and transaction is not writ
- Task bucket doesn't exist and transaction is not writable
- failed to write task_runner state: %v
- failed to read device manager plugin state: %v
- failed to read driver manager plugin state: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/669bf13bc171ccc7.
Report an issue: GitHub.