apache/flink · error · NumberFormatException

negative duration is not supported

Error message

negative duration is not supported

What it means

TimeUtils.parseDuration first tries number+unit parsing; when the text starts with no digits it falls back to ISO-8601 (Duration.parse, e.g. "PT-1.5S" or "-PT10S"). A syntactically valid but negative ISO-8601 duration is rejected with this NumberFormatException because the legacy number+unit format never supported negative durations and Flink keeps that invariant.

Source

Thrown at flink-core/src/main/java/org/apache/flink/util/TimeUtils.java:87

        final int len = trimmed.length();
        int pos = 0;

        char current;
        while (pos < len && (current = trimmed.charAt(pos)) >= '0' && current <= '9') {
            pos++;
        }

        final String number = trimmed.substring(0, pos);
        final String unitLabel = trimmed.substring(pos).trim().toLowerCase(Locale.US);

        if (number.isEmpty()) {
            try {
                // Fall back to parse ISO-8601 duration format
                Duration parsedDuration = Duration.parse(trimmed);
                if (parsedDuration.isNegative()) {
                    // Don't support negative duration which is consistent with before format
                    throw new NumberFormatException("negative duration is not supported");
                }
                return parsedDuration;
            } catch (DateTimeParseException e) {
                throw new NumberFormatException(
                        "text does not start with a number, and is not a valid ISO-8601 duration format: "
                                + trimmed);
            }
        }

        final BigInteger value;
        try {
            value = new BigInteger(number); // this throws a NumberFormatException
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(
                    "The value '" + number + "' cannot be represented as an integer number.", e);
        }

        final ChronoUnit unit;

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Use a non-negative duration; if the intent was 'indefinitely disabled', use the documented sentinel for that option (often -1 as an integer or a specific value like 0/Integer.MAX_VALUE per the option's docs).
  2. Validate durations are >= 0 before formatting them into configuration strings.
  3. If parsing user input, check for a leading '-' and reject with a clear message before calling parseDuration.

Example fix

# before
retry.delay=-PT30S

# after
retry.delay=30 s
Defensive patterns

Strategy: validation

Validate before calling

if (text.trim().startsWith("-") || text.contains("-P") && Duration.parse(text).isNegative()) {
    throw new IllegalArgumentException("Negative durations are not allowed: " + text);
}
Duration d = TimeUtils.parseDuration(text);

Try / catch

try { TimeUtils.parseDuration(text); }
catch (NumberFormatException | IllegalArgumentException e) { /* map to user-facing config error */ }

Prevention

When it happens

Trigger: Calling TimeUtils.parseDuration("-PT30S"), TimeUtils.parseDuration("PT-0.5H"), or any ISO-8601 string whose resulting Duration.isNegative() is true.

Common situations: Porting config from systems that allow negative timeouts (meaning "infinite" or "disabled"); sign errors in generated config; programmatically building duration strings from possibly-negative variables.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/850d4c78832c2253. Report an issue: GitHub.