{"record":{"id":"bb1501d618e30a84","repo":"hashicorp/nomad","slug":"unexpected-notbeforeleeway-type-v","errorCode":null,"errorMessage":"unexpected NotBeforeLeeway type: %v","messagePattern":"unexpected NotBeforeLeeway type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/acl.go","lineNumber":970,"sourceCode":"\t\t\t}\n\t\tcase float64:\n\t\t\tc.ExpirationLeeway = time.Duration(v)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unexpected ExpirationLeeway type: %v\", v)\n\t\t}\n\t}\n\tif aux.NotBeforeLeeway != nil {\n\t\tswitch v := aux.NotBeforeLeeway.(type) {\n\t\tcase string:\n\t\t\tif v != \"\" {\n\t\t\t\tif c.NotBeforeLeeway, err = time.ParseDuration(v); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\tcase float64:\n\t\t\tc.NotBeforeLeeway = time.Duration(v)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unexpected NotBeforeLeeway type: %v\", v)\n\t\t}\n\t}\n\tif aux.ClockSkewLeeway != nil {\n\t\tswitch v := aux.ClockSkewLeeway.(type) {\n\t\tcase string:\n\t\t\tif v != \"\" {\n\t\t\t\tif c.ClockSkewLeeway, err = time.ParseDuration(v); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\tcase float64:\n\t\t\tc.ClockSkewLeeway = time.Duration(v)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unexpected ClockSkewLeeway type: %v\", v)\n\t\t}\n\t}\n\treturn nil\n}","sourceCodeStart":952,"sourceCodeEnd":988,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/acl.go#L952-L988","documentation":"Analogous to the ExpirationLeeway error, this is returned in api/acl.go's custom unmarshal when the NotBeforeLeeway JSON value has an unexpected type. Only duration strings and numeric (float64 nanosecond) values are accepted; anything else fails decoding.","triggerScenarios":"Creating or updating an ACL auth method with a JSON `NotBeforeLeeway` value that is not a string duration or number — e.g. a bool, object, or array.","commonSituations":"Terraform/SDK configs emitting structured duration objects; manual JSON edits with wrong types; copying response JSON back into a request after the field was round-tripped into a different type.","solutions":["Use a Go duration string (e.g. \"30s\", \"2m\") or an integer nanosecond value for NotBeforeLeeway.","Fix the marshaling side so the field is emitted as string/number.","Validate the JSON payload shape against the auth method schema before submitting."],"exampleFix":"// before\n{\"NotBeforeLeeway\": true}\n// after\n{\"NotBeforeLeeway\": \"30s\"}","handlingStrategy":"validation","validationCode":"if !validLeeway(payload.NotBeforeLeeway) {\n    return fmt.Errorf(\"NotBeforeLeeway must be a duration string (e.g. \\\"30s\\\") or numeric nanoseconds\")\n}","typeGuard":"func isDurationOrNumber(v interface{}) bool {\n    switch t := v.(type) {\n    case string:\n        _, err := time.ParseDuration(t)\n        return err == nil\n    case float64:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Use Go's time.Duration marshaling (string) when building auth method payloads.","Document expected field types in internal API client wrappers.","Test unmarshaling round-trips for auth method structs."],"tags":["json","unmarshal","acl","consul-api"],"backgroundTag":"json-type-mismatch","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}