hibernate/hibernate-orm · error · HibernateException
could not parse timestamp string %s
Error message
could not parse timestamp string %s
What it means
JdbcTimestampJavaType.fromString() parses timestamp literals with the strict pattern 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS' in UTC: a space separator and exactly nine fractional digits are required. Text in ISO form ('2024-01-01T10:00:00'), without nanoseconds, or with fewer/more fraction digits throws DateTimeParseException, wrapped as HibernateException("could not parse timestamp string ..."). Used when HQL timestamp literals are parsed and strings are converted to Timestamp.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java:227
default -> false;
};
}
@Override
public String toString(Timestamp value) {
return LITERAL_FORMATTER.format( value.toInstant() );
}
@Override
public Timestamp fromString(CharSequence string) {
try {
final var temporalAccessor = LITERAL_FORMATTER.parse( string );
final var timestamp = new Timestamp( temporalAccessor.getLong( ChronoField.INSTANT_SECONDS ) * 1000L );
timestamp.setNanos( temporalAccessor.get( ChronoField.NANO_OF_SECOND ) );
return timestamp;
}
catch ( DateTimeParseException pe) {
throw new HibernateException( "could not parse timestamp string " + string, pe );
}
}
@Override
public void appendEncodedString(SqlAppender sb, Timestamp value) {
ENCODED_FORMATTER.formatTo( value.toInstant(), sb );
}
@Override
public Timestamp fromEncodedString(CharSequence charSequence, int start, int end) {
try {
final var temporalAccessor = ENCODED_FORMATTER.parse( subSequence( charSequence, start, end ) );
if ( temporalAccessor.isSupported( ChronoField.INSTANT_SECONDS ) ) {
final var timestamp = new Timestamp( temporalAccessor.getLong( ChronoField.INSTANT_SECONDS ) * 1000L );
timestamp.setNanos( temporalAccessor.get( ChronoField.NANO_OF_SECOND ) );
return timestamp;
}
else {View on GitHub (pinned to fad1729dce)
Solutions
- Use typed bind parameters (LocalDateTime, Instant or java.sql.Timestamp) instead of string literals - the recommended fix
- If a literal is required, format it as 'yyyy-MM-dd HH:mm:ss.fffffffff' with all nine fraction digits (e.g. '2024-01-01 10:00:00.000000000')
- Parse the incoming string yourself into a LocalDateTime/Instant and bind the object
- For string columns storing timestamps, add an AttributeConverter with the correct formatter
Example fix
// before
em.createQuery("select e from Log e where e.at = '2024-01-01T10:00:00'") // HibernateException
// after
query = em.createQuery("select e from Log e where e.at = :at", Log.class);
query.setParameter("at", LocalDateTime.parse("2024-01-01T10:00:00")); Defensive patterns
Strategy: validation
Validate before calling
static final java.time.format.DateTimeFormatter HQL_TS =
java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS");
static boolean isParsableTimestampLiteral(CharSequence s) {
try { HQL_TS.parse(s); return true; }
catch (java.time.format.DateTimeParseException e) { return false; }
} Type guard
static java.time.LocalDateTime tryParseHqlTimestamp(String s) {
try { return java.time.LocalDateTime.parse(s.replace(' ', 'T')); }
catch (Exception e) { return null; }
} Try / catch
try { /* query with timestamp literal or fromString */ }
catch (HibernateException e) {
if (e.getCause() instanceof DateTimeParseException)
throw new IllegalArgumentException("Timestamp literal must be 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS'", e);
throw e;
} Prevention
- Never splice timestamp strings into HQL; bind LocalDateTime/Instant/Timestamp parameters
- If a literal is unavoidable, include all 9 fractional digits and a space separator
- Parse external ISO strings yourself before use
When it happens
Trigger: HQL literal ... where e.at = '2024-01-01T10:00:00' or '2024-01-01 10:00:00' (missing .000000000); fromString on strings with 'T' separator; passing a String parameter where a Timestamp is expected by the query.
Common situations: Devs writing ISO-8601 literals in JPQL (natural habit, wrong format here); front-ends sending ISO strings that get spliced into queries; data feeds formatting timestamps with DateTimeFormatter.ISO_LOCAL_DATE_TIME.
Related errors
- could not parse date string %s
- could not parse time string %s
- could not parse timestamp 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/d8d986d8bfa3428f.
Report an issue: GitHub.