hashicorp/nomad · error

variables are limited to 64KiB in total size

Error message

variables are limited to 64KiB in total size

What it means

VariableDecrypted.ValidateForLock rejects any lock-related variable whose serialized Items exceed the 64KiB (maxVariableSize) limit. Nomad caps the total size of a variable's key/value payload so it stays within raft and RPC size budgets. When the payload is too large, the sentinel errQuotaExhausted is returned instead of storing the variable.

Source

Thrown at nomad/structs/variables.go:75

	minVariableLockTTL = 10 * time.Second
	maxVariableLockTTL = 24 * time.Hour

	// defaultLockTTL is the default value used to maintain a lock before it needs to
	// be renewed. The actual value comes from the experience with Consul.
	defaultLockTTL = 15 * time.Second

	// defaultLockDelay is the default a lock will be blocked after the TTL
	// went by without any renews. It is intended to prevent split brain situations.
	// The actual value comes from the experience with Consul.
	defaultLockDelay = 15 * time.Second
)

var (
	errNoPath             = errors.New("missing path")
	errNoNamespace        = errors.New("missing namespace")
	errNoLock             = errors.New("missing lock ID")
	errWildCardNamespace  = errors.New("can not target wildcard (\"*\")namespace")
	errQuotaExhausted     = errors.New("variables are limited to 64KiB in total size")
	errNegativeDelayOrTTL = errors.New("Lock delay and TTL must be positive")
	errInvalidTTL         = errors.New("TTL must be between 10 seconds and 24 hours")
)

// VariableMetadata is the metadata envelope for a Variable, it is the list
// object and is shared data between an VariableEncrypted and a
// VariableDecrypted object.
type VariableMetadata struct {
	Namespace string
	Path      string

	// Lock represents a variable which is used for locking functionality.
	Lock *VariableLock `json:",omitempty"`

	CreateIndex uint64
	CreateTime  int64
	ModifyIndex uint64
	ModifyTime  int64

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Reduce the payload: split the data across multiple variables under different paths so each stays under 64KiB.
  2. Remove unneeded keys or compress/trim large values (store a path/URL to the data instead of the data itself).
  3. Check vd.Items.Size() before calling the API and reject or split oversized payloads in your tooling.

Example fix

// before
variable.Items["big-config"] = string(largeJSONBlob) // > 64KiB total
err := variable.ValidateForLock()
// after
if variable.Items.Size() > 60*1024 {
	parts := splitPayload(largeJSONBlob, 32*1024)
	for i, p := range parts {
		sv := variable.Copy()
		sv.Path = fmt.Sprintf("%s/part%d", variable.Path, i)
		sv.Items = map[string]string{"data": p}
	}
}
Defensive patterns

Strategy: validation

Validate before calling

func variableFits(v structs.VariableDecrypted) bool {
	return v.Items.Size() <= structs.MaxVariableSize // 64KiB
}

Try / catch

if err := vd.ValidateForLock(); err != nil {
	if err.Error() == "variables are limited to 64KiB in total size" {
		return fmt.Errorf("variable %q exceeds 64KiB; split it into smaller variables", vd.Path)
	}
	return err
}

Prevention

When it happens

Trigger: Calling ValidateForLock on a VariableDecrypted whose vd.Items.Size() > maxVariableSize (64KiB); e.g. creating or updating a lock variable whose key/value data totals more than 65536 bytes.

Common situations: Storing large config blobs, certificates, or many keys in a single variable; migrating secrets from Vault/consul-template files verbatim into one Nomad variable; accidentally embedding binary data instead of references.

Related errors


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