hashicorp/nomad · error

unexpected ClockSkewLeeway type: %v

Error message

unexpected ClockSkewLeeway type: %v

What it means

Returned in api/acl.go's unmarshal logic when the ClockSkewLeeway JSON value is neither a duration string nor a float64 (nanoseconds). Part of the same type-switch chain that decodes leeway fields on ACL auth method clock skew configuration.

Source

Thrown at api/acl.go:984

			}
		case float64:
			c.NotBeforeLeeway = time.Duration(v)
		default:
			return fmt.Errorf("unexpected NotBeforeLeeway type: %v", v)
		}
	}
	if aux.ClockSkewLeeway != nil {
		switch v := aux.ClockSkewLeeway.(type) {
		case string:
			if v != "" {
				if c.ClockSkewLeeway, err = time.ParseDuration(v); err != nil {
					return err
				}
			}
		case float64:
			c.ClockSkewLeeway = time.Duration(v)
		default:
			return fmt.Errorf("unexpected ClockSkewLeeway type: %v", v)
		}
	}
	return nil
}

// OIDCClientAssertionKeySource specifies what key material should be used
// to sign an OIDCClientAssertion.
type OIDCClientAssertionKeySource string

const (
	// OIDCKeySourceNomad signs the OIDCClientAssertion JWT with Nomad's
	// internal private key. Its public key is exposed at /.well-known/jwks.json
	OIDCKeySourceNomad OIDCClientAssertionKeySource = "nomad"
	// OIDCKeySourcePrivateKey signs the OIDCClientAssertion JWT with
	// key material defined in OIDCClientAssertion.PrivateKey
	OIDCKeySourcePrivateKey OIDCClientAssertionKeySource = "private_key"
	// OIDCKeySourceClientSecret signs the OIDCClientAssertion JWT with
	// ACLAuthMethod.ClientSecret

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Send ClockSkewLeeway as a duration string like "2m" or numeric nanoseconds.
  2. Fix the producing code/serializer to emit the expected type.
  3. If the field is optional, omit it entirely instead of sending a null/typed placeholder.

Example fix

// before
{"ClockSkewLeeway": ["2", "minutes"]}
// after
{"ClockSkewLeeway": "2m"}
Defensive patterns

Strategy: validation

Validate before calling

if payload.ClockSkewLeeway != nil && !isDurationOrNumber(*payload.ClockSkewLeeway) {
    return fmt.Errorf("ClockSkewLeeway must be a duration string or nanosecond number")
}

Type guard

func coerceClockSkew(v interface{}) (time.Duration, bool) {
    switch t := v.(type) {
    case string:
        d, err := time.ParseDuration(t)
        return d, err == nil
    case float64:
        return time.Duration(t), true
    }
    return 0, false
}

Prevention

When it happens

Trigger: Submitting or decoding auth method JSON where `ClockSkewLeeway` is a non-string, non-numeric value (object, bool, null dereference into the aux interface).

Common situations: Clients building payloads programmatically with incorrectly typed fields; JSON produced by another language where durations serialize as objects; API upgrades changing field encoding expectations.

Related errors


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