hibernate/hibernate-orm · error · HibernateException
could not parse date string %s
Error message
could not parse date string %s
What it means
JdbcDateJavaType.fromString() parses date text using DateTimeFormatter.ISO_LOCAL_DATE, i.e. exactly yyyy-MM-dd. It is the path Hibernate uses to read HQL/JPQL date literals and to convert string data into java.sql.Date. If the text does not match ISO local date (regional format, time part, whitespace), the DateTimeParseException is rethrown as HibernateException("could not parse date string ...").
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java:260
private static TemporalAccessor fromDate(java.util.Date value) {
return value instanceof java.sql.Date date
? date.toLocalDate()
: LocalDate.ofInstant( value.toInstant(), ZoneOffset.systemDefault() );
}
@Override
public String toString(Date value) {
return LITERAL_FORMATTER.format( fromDate( value ) );
}
@Override
public Date fromString(CharSequence string) {
try {
final var temporalAccessor = LITERAL_FORMATTER.parse( string );
return java.sql.Date.valueOf( temporalAccessor.query( LocalDate::from ) );
}
catch ( DateTimeParseException pe) {
throw new HibernateException( "could not parse date string " + string, pe );
}
}
@Override
public Date fromEncodedString(CharSequence charSequence, int start, int end) {
try {
final var temporalAccessor = ENCODED_FORMATTER.parse( subSequence( charSequence, start, end ) );
return java.sql.Date.valueOf( temporalAccessor.query( LocalDate::from ) );
}
catch ( DateTimeParseException pe) {
throw new HibernateException( "could not parse time string " + subSequence( charSequence, start, end ), pe );
}
}
@Override
public void appendEncodedString(SqlAppender sb, Date value) {
LITERAL_FORMATTER.formatTo( fromDate( value ), sb );
}View on GitHub (pinned to fad1729dce)
Solutions
- Rewrite literals and stored text to ISO format yyyy-MM-dd before Hibernate sees them
- In HQL, prefer bind parameters of type LocalDate or java.sql.Date over string literals
- For a text column holding dates in a fixed non-ISO format, add a javax.persistence.AttributeConverter that parses with the matching DateTimeFormatter
- Trim/clean the incoming strings; reject empty strings before they reach the parser
Example fix
// before
em.createQuery("select e from Event e where e.day = '31/12/2024'") // HibernateException
// after
em.createQuery("select e from Event e where e.day = '2024-12-31'")
// or: query.setParameter("day", LocalDate.of(2024,12,31)); Defensive patterns
Strategy: validation
Validate before calling
static boolean isIsoDate(CharSequence s) {
if (s == null) return false;
try { java.time.LocalDate.parse(s); return true; }
catch (java.time.format.DateTimeParseException e) { return false; }
}
// before binding/storing:
if (!isIsoDate(text)) throw new IllegalArgumentException("Expected yyyy-MM-dd: " + text); Type guard
static java.time.LocalDate tryIsoDate(String s) {
try { return java.time.LocalDate.parse(s.trim()); } catch (Exception e) { return null; }
} Try / catch
try {
Date d = JdbcDateJavaType.INSTANCE.fromString(text);
} catch (HibernateException e) {
if (e.getCause() instanceof DateTimeParseException pe)
throw new IllegalArgumentException("Bad date text: '" + text + "' (expected yyyy-MM-DD)", e);
throw e;
} Prevention
- Always bind typed LocalDate/java.sql.Date parameters instead of string literals
- Normalize external date text to ISO with an explicit DateTimeFormatter at the boundary
- Reject empty strings before they reach Hibernate parsing
When it happens
Trigger: An HQL literal such as ... where e.d = '31/12/2024' or '2024.12.31' (only '2024-12-31' parses); calling JdbcDateJavaType.INSTANCE.fromString(...) or JavaType.fromString on a non-ISO string; a String-typed source (native query result, varchar column, XML mapping) coerced into a java.sql.Date attribute with non-ISO content, including empty strings and values with trailing spaces.
Common situations: Data imported from CSV/Excel with regional date formats; native SQL queries returning dates as formatted strings; reports or integrations that hand-formatted dates with SimpleDateFormat('dd/MM/yyyy') before binding; upgrades where hand-written literals no longer parse.
Related errors
- could not parse time string %s
- could not parse timestamp string %s
- could not parse time string %s
- Insert conflict 'do update' clause with constraint name is n
- field type not supported on Derby: " + unit
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d01355b15e616653.
Report an issue: GitHub.