apache/cassandra · error · IllegalArgumentException
Timestamp format must be hh:mm:ss[.fffffffff]
Error message
Timestamp format must be hh:mm:ss[.fffffffff]
What it means
parseTime parses a CQL `time` literal string into nanos-since-midnight. This IllegalArgumentException is the generic format failure: the input is null, has no two colons in the expected hh:mm:ss arrangement, or has a malformed fractional-seconds part. It mirrors the driver-side parser for CQL time values.
Source
Thrown at src/java/org/apache/cassandra/cql3/functions/types/ParseUtils.java:399
* @param str The string to parse.
* @return A long value representing the number of nanoseconds since midnight.
* @throws ParseException if the string cannot be parsed.
* @see <a href="https://cassandra.apache.org/doc/cql3/CQL-2.2.html#usingtime">'Working with time'
* section of CQL specification</a>
*/
static long parseTime(String str) throws ParseException
{
String nanos_s;
long hour;
long minute;
long second;
long a_nanos = 0;
String formatError = "Timestamp format must be hh:mm:ss[.fffffffff]";
String zeros = "000000000";
if (str == null) throw new IllegalArgumentException(formatError);
str = str.trim();
// Parse the time
int firstColon = str.indexOf(':');
int secondColon = str.indexOf(':', firstColon + 1);
// Convert the time; default missing nanos
if (firstColon > 0 && secondColon > 0 && secondColon < str.length() - 1)
{
int period = str.indexOf('.', secondColon + 1);
hour = Integer.parseInt(str.substring(0, firstColon));
if (hour < 0 || hour >= 24) throw new IllegalArgumentException("Hour out of bounds.");
minute = Integer.parseInt(str.substring(firstColon + 1, secondColon));
if (minute < 0 || minute >= 60) throw new IllegalArgumentException("Minute out of bounds.");
if (period > 0 && period < str.length() - 1)
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Normalize the input to hh:mm:ss before parsing, e.g. expand "01:30" to "01:30:00".
- Strip/convert alternate formats (AM/PM, ISO-8601 durations) to hh:mm:ss[.fffffffff] with a pre-parser.
- Validate with a regex ^\d{1,2}:\d{2}:\d{2}(\.\d{1,9})?$ before calling parseTime.
- Catch IllegalArgumentException and surface a user-friendly message naming the expected format.
Example fix
// before
long nanos = ParseUtils.parseTime("01:30 PM"); // throws
// after
String normalized = "01:30 PM".replace(" PM", ""); // better: convert to 24h
long nanos = ParseUtils.parseTime(normalized + ":00"); // "13:30:00" Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern TIME = Pattern.compile("^\\d{1,2}:\\d{2}:\\d{2}(\\.\\d{1,9})?$");
if (str == null || !TIME.matcher(str.trim()).matches())
throw new IllegalArgumentException("time must be hh:mm:ss[.fffffffff]: " + str); Try / catch
try { return ParseUtils.parseTime(s); }
catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid time literal '" + s + "': " + e.getMessage(), e); } Prevention
- Validate time strings with a regex before parsing
- Normalize user/CSV input (add :00 seconds, strip AM/PM) up front
- Never pass null or untrimmed raw input to parseTime
When it happens
Trigger: Calling ParseUtils.parseTime(null); passing a string without colons (e.g. "1230"); only one colon ("12:30"); trailing colon with nothing after second colon ("12:30:"); a fractional part longer than 9 digits or starting with a non-digit; or a trailing dot like "12:30:30." (parsed via the ParseException path at the same message).
Common situations: Reading `time` columns from user input, CSV/JSON imports, or config files where values like "1:30" (single leading digit is fine, but "1h30m" or "01:30 PM" are not), ISO-8601 durations ("PT1H30M"), or "hh:mm" without seconds are supplied instead of hh:mm:ss[.fffffffff].
Related errors
- Unable to convert '%s' to a duration
- Hour out of bounds.
- Minute out of bounds.
- Second out of bounds.
- Invalid or malformed
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/28a7dfeea7848c98.
Report an issue: GitHub.