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

  1. Check whether the alloc bucket was deleted (e.g. by GC) and treat the error as 'alloc state absent'
  2. Use a writable Update transaction if the caller should create the alloc bucket
  3. Reconcile allocID against the client's tracked allocations; stale IDs will never have buckets
  4. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/669bf13bc171ccc7. Report an issue: GitHub.