{"record":{"id":"ec72246fd28691d4","repo":"hibernate/hibernate-orm","slug":"illegal-format-pattern","errorCode":null,"errorMessage":"Illegal format pattern '{}'","messagePattern":"Illegal format pattern '(.+?)'","errorType":"exception","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmFormat.java","lineNumber":53,"sourceCode":"\t// a AM/PM\n\t// H hour of day (0-23)\n\t// h clock hour of am/pm (1-12)\n\t// m minute of hour\n\t// s second of minute\n\t// S fraction of second\n\t// z time zone name e.g. PST\n\t// x zone offset e.g. +03, +0300, +03:00\n\t// Z zone offset e.g. +0300\n\t// see https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html\n\tprivate static final Pattern FORMAT = Pattern.compile( \"('[^']+'|[:;/,.!@#$^&?~`|()\\\\[\\\\]{}<>\\\\-+*=]|\\\\s|G{1,2}|[yY]{1,4}|M{1,4}|w{1,2}|W|E{3,4}|e{1,2}|d{1,2}|D{1,3}|a|[Hhms]{1,2}|S{1,6}|[zZx]{1,3})*\");\n\n\tpublic SqmFormat(\n\t\t\tString value,\n\t\t\tSqmBindableType<String> inherentType,\n\t\t\tNodeBuilder nodeBuilder) {\n\t\tsuper(value, inherentType, nodeBuilder);\n\t\tif (!FORMAT.matcher(value).matches()) {\n\t\t\tthrow new SemanticException(\"Illegal format pattern '\" + value + \"'\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic @Nonnull SqmBindableType<String> getNodeType() {\n\t\treturn castNonNull( super.getNodeType() );\n\t}\n\n\t@Override\n\tpublic @Nonnull String getLiteralValue() {\n\t\treturn castNonNull( super.getLiteralValue() );\n\t}\n\n\t@Override\n\tpublic SqmFormat copy(SqmCopyContext context) {\n\t\tfinal SqmFormat existing = context.getCopy( this );\n\t\tif ( existing != null ) {\n\t\t\treturn existing;","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmFormat.java#L35-L71","documentation":"The HQL format() function wraps its datetime pattern in an SqmFormat node whose constructor validates the pattern against a whitelist regex of supported DateTimeFormatter elements: quoted literals, punctuation separators, whitespace, and limited runs of G, y/Y, M, w, W, E, e, d, D, a, H/h/m/s, S, z/Z/x. Any pattern outside this subset throws SemanticException('Illegal format pattern ...') at query interpretation time.","triggerScenarios":"format( x.ts as '...' ) (or the criteria equivalent) with unsupported letters: u or uuuu years, Q/q quarters, L standalone month, c localized day, A milli-of-day, n nanos, or a letter repeated more times than allowed (e.g. six+ E's, seven+ S's); unbalanced quotes also fail to match.","commonSituations":"Copying a working java.time DateTimeFormatter pattern straight into HQL; quarter-based reporting patterns (QQ yyyy); strftime-style tokens (%Y-%m) or moment.js patterns pasted into the format string.","solutions":["Rewrite the pattern using only supported elements: u -> y, quarter -> month or precomputed quoted text.","Wrap literal characters (including unsupported letters used as text) in single quotes: 'Q' or 'T'.","Do complex formatting in Java after fetching, or fall back to a native query with the dialect's own format function when the pattern cannot be expressed."],"exampleFix":"-- before\nselect format( e.ts as 'yyyy QQ u' ) from Event e  -- Q and u not supported\n\n-- after\nselect format( e.ts as 'yyyy MM dd' ) from Event e","handlingStrategy":"validation","validationCode":"private static final Pattern HQL_FORMAT = Pattern.compile(\n    \"('[^']+'|[:;/,.!@#$^&?~`|()\\\\[\\\\]{}<>\\\\-+*=]|\\\\s|G{1,2}|[yY]{1,4}|M{1,4}|w{1,2}|W|E{3,4}|e{1,2}|d{1,2}|D{1,3}|a|[Hhms]{1,2}|S{1,6}|[zZx]{1,3})*\");\n\nstatic String checkHqlFormat(String pattern) {\n    if ( !HQL_FORMAT.matcher( pattern ).matches() ) {\n        throw new IllegalArgumentException( \"Pattern not supported by HQL format(): \" + pattern );\n    }\n    return pattern;\n}","typeGuard":null,"tryCatchPattern":"try {\n    return em.createQuery( hql ).getResultList();\n} catch ( org.hibernate.query.SemanticException e ) {\n    throw new IllegalArgumentException( \"Bad format pattern: \" + e.getMessage(), e );\n}","preventionTips":["Restrict format patterns to the documented HQL subset (G, y/Y, M, w, W, E, e, d, D, a, H/h/m/s, S, z/Z/x, quoted text, separators).","Validate user-supplied patterns against the same whitelist before building the query.","Format datetimes in Java unless the database must do the formatting."],"tags":["hibernate","hql","format","datetime-pattern","semantic-exception"],"backgroundTag":"invalid-format-pattern","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}