hashicorp/nomad · error
unexpected NotBeforeLeeway type: %v
Error message
unexpected NotBeforeLeeway type: %v
What it means
While decoding an ACL auth method's leeway settings from JSON, NotBeforeLeeway had an unexpected type (neither string nor number); the type switch in UnmarshalJSON rejects values it cannot convert to a duration.
Source
Thrown at nomad/structs/acl.go:1692
}
case float64:
a.ExpirationLeeway = time.Duration(v)
default:
return fmt.Errorf("unexpected ExpirationLeeway type: %v", v)
}
}
if aux.NotBeforeLeeway != nil {
switch v := aux.NotBeforeLeeway.(type) {
case string:
if v != "" {
if a.NotBeforeLeeway, err = time.ParseDuration(v); err != nil {
return err
}
}
case float64:
a.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 a.ClockSkewLeeway, err = time.ParseDuration(v); err != nil {
return err
}
}
case float64:
a.ClockSkewLeeway = time.Duration(v)
default:
return fmt.Errorf("unexpected ClockSkewLeeway type: %v", v)
}
}
return nil
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Send NotBeforeLeeway as a duration string like "30s" or "2m".
- Or send a nanosecond number (e.g. 30000000000 for 30s).
- Validate the rendered JSON payload shape before POSTing it to the API.
Example fix
// before
{"NotBeforeLeeway": {"value": 30, "unit": "s"}}
// after
{"NotBeforeLeeway": "30s"} Defensive patterns
Strategy: type-guard
Validate before calling
switch v := raw["NotBeforeLeeway"].(type) {
case string, float64:
// ok
default:
return fmt.Errorf("NotBeforeLeeway must be a duration string or number, got %T", v)
} Type guard
func isDurationScalar(v interface{}) bool {
switch v.(type) {
case string, float64, float32, int64:
return true
}
return false
} Try / catch
if err := json.Unmarshal(payload, &am); err != nil {
if strings.Contains(err.Error(), "unexpected NotBeforeLeeway type") {
return fmt.Errorf("send NotBeforeLeeway as e.g. \"30s\" or a nanosecond number")
}
return err
} Prevention
- Same rule as ExpirationLeeway: string duration or nanosecond number only
- Diff rendered JSON against a known-good auth-method payload before POST
- Validate payload shape in CI for generated configs
When it happens
Trigger: Submitting auth-method JSON where NotBeforeLeeway is a boolean, nested object, or array instead of a string duration or number.
Common situations: Copy-paste typos in the JWT/OIDC config block (putting the leeway under the wrong key as a map); template renderers emitting structured duration objects; editing config via UIs that serialize durations as objects.
Related errors
- unexpected ExpirationLeeway type: %v
- unexpected ExpirationLeeway type: %v
- unexpected NotBeforeLeeway type: %v
- unexpected ClockSkewLeeway type: %v
- ACL policy not found
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d1d781d217a75f5e.
Report an issue: GitHub.