prestodb/presto · error · IllegalArgumentException

Invalid year-month interval:

Error message

Invalid year-month interval: 

What it means

IntervalYearMonth.parseMonths parses a year-month interval string (e.g. '1-6') using the FORMAT regex. If the string does not match the '<years>-<months>' shape, this IllegalArgumentException is thrown with the offending value appended to the message.

Source

Thrown at presto-client/src/main/java/com/facebook/presto/client/IntervalYearMonth.java:71

        return format("%s%d-%d", sign, months / 12, months % 12);
    }

    public static int parseMonths(String value)
    {
        if (value.equals(INT_MIN_VALUE)) {
            return Integer.MIN_VALUE;
        }

        int signum = 1;
        if (value.startsWith("-")) {
            signum = -1;
            value = value.substring(1);
        }

        Matcher matcher = FORMAT.matcher(value);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("Invalid year-month interval: " + value);
        }

        int years = parseInt(matcher.group(1));
        int months = parseInt(matcher.group(2));

        return toMonths(years, months) * signum;
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Check the input matches '<years>-<months>' (optionally signed, e.g. '-1-6').
  2. Normalize before parsing: convert '18 months' style input to years/months form like '1-6' yourself.
  3. Wrap parseMonths in try-catch and show the expected format in the error message.
  4. Route day-time interval strings to IntervalDayTime.parseMillis instead.

Example fix

// before
int months = IntervalYearMonth.parseMonths(userInput); // throws on '1y6m'
// after
Matcher m = Pattern.compile("(-?)(\\d+)-(\\d+)").matcher(userInput.trim());
if (!m.matches()) { throw new IllegalArgumentException("Expected format: years-months, e.g. 1-6"); }
int months = IntervalYearMonth.parseMonths(m.group(1) + m.group(2) + "-" + m.group(3));
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern INTERVAL_YEAR_MONTH = Pattern.compile("-?\\d+-\\d+");
if (value == null || !INTERVAL_YEAR_MONTH.matcher(value.trim()).matches()) {
    throw new IllegalArgumentException("Expected year-month interval like '1-6', got: " + value);
}

Try / catch

try { int months = IntervalYearMonth.parseMonths(value); } catch (IllegalArgumentException e) { /* surface expected 'years-months' format */ }

Prevention

When it happens

Trigger: Calling IntervalYearMonth.parseMonths with strings like '18 months', '1y6m', a day-time string such as '1 12:00:00.000', or values with wrong separator (e.g. '1:6' instead of '1-6') that fail the FORMAT regex.

Common situations: Mixing up the two interval types (passing day-time syntax to the year-month parser); constructing intervals from user input without format validation; values taken from logs or other systems with different interval notations.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/a02a2ce38303b9bc. Report an issue: GitHub.