{"record":{"id":"088cb8df35864909","repo":"keycloak/keycloak","slug":"unable-not-parse-a-date-using-format","errorCode":null,"errorMessage":"Unable not parse a date using format [{}]","messagePattern":"Unable not parse a date using format \\[(.+?)\\]","errorType":"validation","errorClass":"PolicyValidationException","httpStatus":null,"severity":"warning","filePath":"authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java","lineNumber":168,"sourceCode":"\n        config.compute(\"year\", (s, s2) -> representation.getYear() != null ? representation.getYear() : null);\n        config.compute(\"yearEnd\", (s, s2) -> representation.getYearEnd() != null ? representation.getYearEnd() : null);\n\n        config.compute(\"hour\", (s, s2) -> representation.getHour() != null ? representation.getHour() : null);\n        config.compute(\"hourEnd\", (s, s2) -> representation.getHourEnd() != null ? representation.getHourEnd() : null);\n\n        config.compute(\"minute\", (s, s2) -> representation.getMinute() != null ? representation.getMinute() : null);\n        config.compute(\"minuteEnd\", (s, s2) -> representation.getMinuteEnd() != null ? representation.getMinuteEnd() : null);\n\n        policy.setConfig(config);\n    }\n\n    private void validateFormat(String notBefore, String notOnOrAfter) {\n        Date nbf, noa;\n        try {\n            nbf = new SimpleDateFormat(TimePolicyProvider.DEFAULT_DATE_PATTERN).parse(TimePolicyProvider.format(notBefore));\n        } catch (Exception e) {\n            throw new PolicyValidationException(\"Unable not parse a date using format [\" + notBefore + \"]\");\n        }\n        try {\n            noa = new SimpleDateFormat(TimePolicyProvider.DEFAULT_DATE_PATTERN).parse(TimePolicyProvider.format(notOnOrAfter));\n        } catch (Exception e) {\n            throw new PolicyValidationException(\"Unable not parse a date using format [\" + notOnOrAfter + \"]\");\n        }\n        if (noa.before(nbf)) {\n            throw new PolicyValidationException(\"Expire time can't be set to a date before start time\");\n        }\n    }\n}\n","sourceCodeStart":150,"sourceCodeEnd":180,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java#L150-L180","documentation":"Thrown as a PolicyValidationException (HTTP 400) by TimePolicyProviderFactory.validateFormat() when the 'notBefore' date string cannot be parsed using the format 'yyyy-MM-dd HH:mm:ss'. validateFormat() is called during policy create and update (onCreate/onUpdate) when both notBefore and notOnOrAfter are non-null. Note: the message contains a typo ('Unable not parse' should be 'Unable to parse').","triggerScenarios":"POST or PUT to .../policy/time with a notBefore value that doesn't match 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd'. Example: notBefore = '01/15/2024' or 'Jan 15 2024'.","commonSituations":"Client using a locale-specific date format (MM/DD/YYYY vs yyyy-MM-dd). Missing time component when the server expects full datetime. Timezone-annotated strings (ISO-8601 with 'T' or 'Z') that don't match the expected space-separated format. Copy-pasting dates from a spreadsheet in a different format.","solutions":["Format notBefore as 'yyyy-MM-dd HH:mm:ss', e.g. '2024-01-15 00:00:00'. A bare date 'yyyy-MM-dd' is also accepted (auto-extended to midnight).","If sending via API, use a date formatter in your client code to produce the exact format.","Do not use 'T' separators or 'Z' suffixes — use a space between date and time.","Validate the date string client-side before submitting."],"exampleFix":"// before\nrep.setNotBefore(\"2024/01/15T08:00:00Z\");\n\n// after\nrep.setNotBefore(\"2024-01-15 08:00:00\");","handlingStrategy":"validation","validationCode":"// Before creating/updating a time policy, validate notBefore format\nString notBefore = rep.getNotBefore();\nif (notBefore != null && notOnOrAfter != null) {\n    SimpleDateFormat fmt = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n    try {\n        fmt.parse(notBefore.trim().length() == 10 ? notBefore.trim() + \" 00:00:00\" : notBefore);\n    } catch (ParseException e) {\n        throw new IllegalArgumentException(\n            \"notBefore must be 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd', got: \" + notBefore);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    policyResource.create(rep);\n} catch (BadRequestException e) {\n    if (e.getMessage().contains(\"Unable not parse a date using format\")) {\n        showError(\"Invalid date format. Use yyyy-MM-dd HH:mm:ss (e.g., 2024-01-15 00:00:00).\");\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always format notBefore as 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd'.","Use a date formatter in client code rather than constructing strings manually.","Do not use slashes, 'T' separators, or timezone suffixes in date strings."],"tags":["keycloak","authorization","time-policy","date-parsing","validation","bad-request"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}