apache/cassandra · error · MarshalException

(TimeType) Unable to coerce '%s' to a formatted time (long)

Error message

(TimeType) Unable to coerce '%s' to a formatted time (long)

What it means

When the input is not a plain long, TimeSerializer attempts strict time-string parsing via parseTimeStrictly (formats like hh:mm:ss[.fraction], optionally with suffixes). IllegalArgumentException from that parser is wrapped as this MarshalException, meaning the string could not be coerced to a time-of-day long.

Source

Thrown at src/java/org/apache/cassandra/serializers/TimeSerializer.java:67

                long result = Long.parseLong(source);
                if (result < 0 || result >= TimeUnit.DAYS.toNanos(1))
                    throw new NumberFormatException("Input long out of bounds: " + source);
                return result;
            }
            catch (NumberFormatException e)
            {
                throw new MarshalException(String.format("Unable to make long (for time) from: '%s'", source), e);
            }
        }

        // Last chance, attempt to parse as time string
        try
        {
            return parseTimeStrictly(source);
        }
        catch (IllegalArgumentException e1)
        {
            throw new MarshalException(String.format("(TimeType) Unable to coerce '%s' to a formatted time (long)", source), e1);
        }
    }

    public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException
    {
        if (accessor.size(value) != 8)
            throw new MarshalException(String.format("Expected 8 byte long for time (%d)", accessor.size(value)));
    }

    @Override
    public boolean shouldQuoteCQLLiterals()
    {
        return true;
    }

    public String toString(Long value)
    {
        if (value == null)

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Use the strict format HH:MM:SS[.fffffffff] with 24-hour hours (00-23), e.g. '13:30:54.234'
  2. Clamp/validate hour<=23, minute<=59, second<=59 before sending
  3. Pass a plain long of nanoseconds since midnight instead of a string
  4. Use a driver DateRange/Time codec or LocalTime object so the driver formats it correctly

Example fix

// before
session.execute("INSERT INTO t (tm) VALUES (?)", "1:30 PM");
// after
session.execute("INSERT INTO t (tm) VALUES (?)", "13:30:00");
Defensive patterns

Strategy: validation

Validate before calling

// strict 24h time-of-day check
if (!input.matches("^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\.\\d{1,9})?)?$")) throw new IllegalArgumentException("unsupported time format: " + input);

Type guard

boolean isValidCqlTimeString(String s) {
  try { LocalTime.parse(s); return true; } catch (DateTimeParseException e) { return false; }
}

Try / catch

try {
  long nanos = TimeSerializer.timeStringToLong(input);
} catch (MarshalException e) {
  throw new BadRequestException("use 24-hour HH:MM:SS[.fraction] time strings");
}

Prevention

When it happens

Trigger: Inserting strings like '25:00:00' (hour out of range), '12:60:00', '1pm', '2020-01-01 12:00:00' (full datetime), or '12:00' variants unsupported by the strict parser into a time column.

Common situations: 12-hour clock strings with AM/PM; datetime strings pasted where only time-of-day is allowed; locale formats like '12.00 Uhr'; hour/min/sec out of bounds from user input.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/34f301c333805d16. Report an issue: GitHub.