hashicorp/nomad · error

TTL must be between 10 seconds and 24 hours

Error message

TTL must be between 10 seconds and 24 hours

What it means

VariableLock.Validate requires the lock TTL to be within [minVariableLockTTL, maxVariableLockTTL] — between 10 seconds and 24 hours per the message. A TTL outside this range (zero, too small, or exceeding 24h) triggers errInvalidTTL. This prevents locks that expire immediately or linger for days.

Source

Thrown at nomad/structs/variables.go:77

	// 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. Set TTL to a duration between 10 seconds and 24 hours (e.g. 30 * time.Second).
  2. Clamp the TTL after parsing: if ttl < 10s use 10s; if ttl > 24h use 24h.
  3. Check the units of externally supplied TTL values (ms vs ns) and convert to time.Duration correctly.

Example fix

// before
lock := &structs.VariableLock{TTL: 5 * time.Second} // below minVariableLockTTL
// after
lock := &structs.VariableLock{LockDelay: 5 * time.Second, TTL: 30 * time.Second}
Defensive patterns

Strategy: validation

Validate before calling

const (
	minTTL = 10 * time.Second
	maxTTL = 24 * time.Hour
)
func lockTTLValid(ttl time.Duration) bool {
	return ttl >= minTTL && ttl <= maxTTL
}

Try / catch

if err := lock.Validate(); err != nil {
	if strings.Contains(err.Error(), "TTL must be between") {
		return fmt.Errorf("lock TTL %s out of range [10s, 24h]", lock.TTL)
	}
	return err
}

Prevention

When it happens

Trigger: Setting VariableLock.TTL below 10 seconds (including 0) or above 24 hours and calling Validate; reproduced in TestStructs_Lock_Validate with an out-of-range TTL and LockDelay: 5 * time.Second.

Common situations: Using time.Duration literals in wrong units (e.g. 5 * time.Second when 5 * time.Minute intended); passing a TTL in milliseconds from another system without converting; leaving TTL unset so it is 0.

Related errors


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