{"record":{"id":"0d8b43c3ac36fcef","repo":"hashicorp/nomad","slug":"unexpected-clockskewleeway-type-v","errorCode":null,"errorMessage":"unexpected ClockSkewLeeway type: %v","messagePattern":"unexpected ClockSkewLeeway type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/acl.go","lineNumber":984,"sourceCode":"\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}\n\n// OIDCClientAssertionKeySource specifies what key material should be used\n// to sign an OIDCClientAssertion.\ntype OIDCClientAssertionKeySource string\n\nconst (\n\t// OIDCKeySourceNomad signs the OIDCClientAssertion JWT with Nomad's\n\t// internal private key. Its public key is exposed at /.well-known/jwks.json\n\tOIDCKeySourceNomad OIDCClientAssertionKeySource = \"nomad\"\n\t// OIDCKeySourcePrivateKey signs the OIDCClientAssertion JWT with\n\t// key material defined in OIDCClientAssertion.PrivateKey\n\tOIDCKeySourcePrivateKey OIDCClientAssertionKeySource = \"private_key\"\n\t// OIDCKeySourceClientSecret signs the OIDCClientAssertion JWT with\n\t// ACLAuthMethod.ClientSecret","sourceCodeStart":966,"sourceCodeEnd":1002,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/acl.go#L966-L1002","documentation":"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.","triggerScenarios":"Submitting or decoding auth method JSON where `ClockSkewLeeway` is a non-string, non-numeric value (object, bool, null dereference into the aux interface).","commonSituations":"Clients building payloads programmatically with incorrectly typed fields; JSON produced by another language where durations serialize as objects; API upgrades changing field encoding expectations.","solutions":["Send ClockSkewLeeway as a duration string like \"2m\" or numeric nanoseconds.","Fix the producing code/serializer to emit the expected type.","If the field is optional, omit it entirely instead of sending a null/typed placeholder."],"exampleFix":"// before\n{\"ClockSkewLeeway\": [\"2\", \"minutes\"]}\n// after\n{\"ClockSkewLeeway\": \"2m\"}","handlingStrategy":"validation","validationCode":"if payload.ClockSkewLeeway != nil && !isDurationOrNumber(*payload.ClockSkewLeeway) {\n    return fmt.Errorf(\"ClockSkewLeeway must be a duration string or nanosecond number\")\n}","typeGuard":"func coerceClockSkew(v interface{}) (time.Duration, bool) {\n    switch t := v.(type) {\n    case string:\n        d, err := time.ParseDuration(t)\n        return d, err == nil\n    case float64:\n        return time.Duration(t), true\n    }\n    return 0, false\n}","tryCatchPattern":null,"preventionTips":["Omit optional leeway fields instead of sending typed placeholders.","Keep one shared JSON model for auth methods between producer and consumer.","Cover leeway encoding in integration tests."],"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"}