prestodb/presto · error · IllegalArgumentException
Invalid year month interval qualifier: to
Error message
Invalid year month interval qualifier: to
What it means
DateTimeUtils.parseYearMonthInterval parses YEAR–MONTH range interval literals (e.g. INTERVAL '2-6' YEAR TO MONTH). Only YEAR, YEAR TO MONTH, and MONTH qualifiers are legal; any other start/end combination throws this IllegalArgumentException naming the invalid qualifier pair.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/util/DateTimeUtils.java:524
}
public static long parseYearMonthInterval(String value, IntervalField startField, Optional<IntervalField> endField)
{
IntervalField end = endField.orElse(startField);
if (startField == IntervalField.YEAR && end == IntervalField.MONTH) {
PeriodFormatter periodFormatter = INTERVAL_YEAR_MONTH_FORMATTER;
return parsePeriodMonths(value, periodFormatter, startField, end);
}
if (startField == IntervalField.YEAR && end == IntervalField.YEAR) {
return parsePeriodMonths(value, INTERVAL_YEAR_FORMATTER, startField, end);
}
if (startField == IntervalField.MONTH && end == IntervalField.MONTH) {
return parsePeriodMonths(value, INTERVAL_MONTH_FORMATTER, startField, end);
}
throw new IllegalArgumentException("Invalid year month interval qualifier: " + startField + " to " + end);
}
private static long parsePeriodMonths(String value, PeriodFormatter periodFormatter, IntervalField startField, IntervalField endField)
{
try {
Period period = parsePeriod(periodFormatter, value);
return IntervalYearMonth.toMonths(
period.getValue(YEAR_FIELD),
period.getValue(MONTH_FIELD));
}
catch (IllegalArgumentException e) {
throw invalidInterval(e, value, startField, endField);
}
}
private static Period parsePeriod(PeriodFormatter periodFormatter, String value)
{
boolean negative = value.startsWith("-");View on GitHub (pinned to 55bb57d202)
Solutions
- Ensure the qualifier is YEAR, YEAR TO MONTH, or MONTH and the value matches (e.g. '2-6')
- Route DAY/HOUR/MINUTE/SECOND combinations to parseDayTimeInterval instead
- Validate the qualifier string against the allowed set before invoking the parser
- Fix reversed fields such as MONTH TO YEAR — Presto requires start <= end in the field hierarchy
Example fix
-- before INTERVAL '1-2' MONTH TO YEAR -- after INTERVAL '1-2' YEAR TO MONTH
Defensive patterns
Strategy: validation
Validate before calling
boolean valid = (start == IntervalField.YEAR && (end == IntervalField.YEAR || end == IntervalField.MONTH)) || (start == IntervalField.MONTH && end == IntervalField.MONTH);
Try / catch
try { return parseYearMonthInterval(value, start, end); } catch (IllegalArgumentException e) { return parseDayTimeInterval(value, start, end); } Prevention
- Only YEAR, YEAR TO MONTH, MONTH qualifiers belong here
- Never pass DAY/HOUR/MINUTE/SECOND fields to this parser
- Reject reversed qualifiers like MONTH TO YEAR at the grammar/config layer
When it happens
Trigger: Calling parseYearMonthInterval with day/time fields (e.g. startField=DAY or end=SECOND), which belong to the DAY–SECOND parser, or a nonsensical combination like MONTH TO YEAR.
Common situations: Routing mistakes where a DAY TO SECOND literal is sent to the year-month parser; user SQL like INTERVAL '1-2' DAY TO HOUR incorrectly typed; code building interval qualifiers dynamically from config without validation.
Related errors
- Invalid day second interval qualifier: to
- INVALID_FUNCTION_ARGUMENT
- Invalid timestamp '%s'
- Invalid time '%s'
- Invalid interval qualifier: to
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/3bbc058831be76cd.
Report an issue: GitHub.