hashicorp/nomad · error

max_identity_ttl must be greater than or equal to default_id

Error message

max_identity_ttl must be greater than or equal to default_identity_ttl

What it means

Config validation appends this error to a multierror when MaxIdentityTTL is strictly less than DefaultIdentityTTL. The maximum TTL is an upper bound for issued identity tokens, so it must be greater than or equal to the default TTL; otherwise every token would violate its own ceiling.

Source

Thrown at nomad/structs/node.go:943

	switch n.Enforcement {
	case NodeIntroductionEnforcementNone,
		NodeIntroductionEnforcementWarn,
		NodeIntroductionEnforcementStrict:
	default:
		mErr = multierror.Append(mErr, fmt.Errorf("invalid enforcement %q", n.Enforcement))
	}

	if n.DefaultIdentityTTL < 1 {
		mErr = multierror.Append(mErr, errors.New("default_identity_ttl must be greater than 0"))
	}

	if n.MaxIdentityTTL < 1 {
		mErr = multierror.Append(mErr, errors.New("max_identity_ttl must be greater than 0"))
	}

	if n.MaxIdentityTTL < n.DefaultIdentityTTL {
		mErr = multierror.Append(mErr, errors.New(
			"max_identity_ttl must be greater than or equal to default_identity_ttl",
		))
	}

	return mErr.ErrorOrNil()
}

// NodeIntroductionIdentityClaims contains the claims for node introduction.
type NodeIntroductionIdentityClaims struct {
	NodePool string `json:"nomad_node_pool"`
	NodeName string `json:"nomad_node_name"`
}

// GenerateNodeIntroductionIdentityClaims generates a new identity JWT for node
// introduction.
//
// The caller is responsible for ensuring that the passed arguments are valid.
func GenerateNodeIntroductionIdentityClaims(name, pool, region string, ttl time.Duration) *IdentityClaims {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Raise max_identity_ttl so it is >= default_identity_ttl (e.g. default "1h", max "12h").
  2. Alternatively lower default_identity_ttl to fit under the configured maximum.
  3. Read the full multierror list — this often appears together with the two 'must be greater than 0' TTL errors — and fix all three constraints in one edit.

Example fix

# before
node {
  default_identity_ttl = "12h"
  max_identity_ttl = "1h"
}
# after
node {
  default_identity_ttl = "1h"
  max_identity_ttl = "12h"
}
Defensive patterns

Strategy: validation

Validate before calling

if cfg.MaxIdentityTTL < cfg.DefaultIdentityTTL {
	return fmt.Errorf("max_identity_ttl (%d) must be >= default_identity_ttl (%d)", cfg.MaxIdentityTTL, cfg.DefaultIdentityTTL)
}

Try / catch

if err := ll.Start(ctx, fns...); err != nil {
	if strings.Contains(err.Error(), "max_identity_ttl must be greater than or equal to default_identity_ttl") {
		return fmt.Errorf("reorder identity TTL bounds: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Configuring max_identity_ttl to a smaller duration than default_identity_ttl (e.g. default "12h" with max "1h") and starting the agent, yielding the aggregated multierror with this message.

Common situations: Operators tuning the max downward after already raising the default, forgetting the ordering constraint; configs merged from two sources where one raised default_identity_ttl; typo'd duration units (e.g. max "1h" vs default "12h" intended as "1d").

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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