apple/pkl · error · ArithmeticException

Cannot convert Pkl duration `${duration}` to ISO 8601 durati

Error message

Cannot convert Pkl duration `${duration}` to ISO 8601 duration.

What it means

DurationUtils.toIsoString converts a Pkl duration (value + unit) to an ISO 8601 duration string. If the computed total number of seconds is not finite (NaN or Infinity, e.g. from overflow of very large values), the conversion is impossible and an ArithmeticException is thrown.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/util/DurationUtils.java:33

 */
package org.pkl.core.util;

import org.pkl.core.DurationUnit;

public final class DurationUtils {
  private DurationUtils() {}

  public static String toPklString(double value, DurationUnit unit) {
    return MathUtils.isMathematicalInteger(value) ? (long) value + "." + unit : value + "." + unit;
  }

  // see: https://standards.calconnect.org/csd/cc-18011.html#toc32
  public static String toIsoString(double value, DurationUnit unit) {
    // different rounding behavior from `VmDuration.convertValueTo()`
    var totalSeconds = value * (unit.getNanos() / 1e9);

    if (!Double.isFinite(totalSeconds)) {
      throw new ArithmeticException(
          "Cannot convert Pkl duration `"
              + DurationUtils.toPklString(value, unit)
              + "` to ISO 8601 duration.");
    }

    var absoluteSeconds = Math.abs(totalSeconds);
    var hours = (long) (absoluteSeconds / 3600);
    var minutes = (long) (absoluteSeconds / 60) % 60;
    var seconds = (long) (absoluteSeconds % 60);
    var nanos =
        (long) (absoluteSeconds * 1_000_000_000 - Math.floor(absoluteSeconds) * 1_000_000_000);

    var builder = new StringBuilder();

    if (totalSeconds < 0.0) {
      builder.append('-');
    }

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Check the duration value is finite and within a sane range before calling toIsoString.
  2. Fix the upstream computation that produced NaN/Infinity.
  3. Clamp or split extremely large durations into finite second totals before conversion.

Example fix

// before
var iso = DurationUtils.toIsoString(hugeValue, DurationUnit.HOURS);
// after
if (Double.isFinite(hugeValue) && hugeValue < 1e15) {
  var iso = DurationUtils.toIsoString(hugeValue, DurationUnit.HOURS);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!Double.isFinite(value)) throw new IllegalArgumentException("duration value must be finite");

Try / catch

try { return DurationUtils.toIsoString(value, unit); } catch (ArithmeticException e) { log.warn("non-finite duration: {}", e.getMessage()); return null; }

Prevention

When it happens

Trigger: Calling toIsoString with a value so large that value * (unit.getNanos()/1e9) overflows to Double.POSITIVE_INFINITY/NEGATIVE_INFINITY, or a value/unit combination yielding NaN.

Common situations: Passing absurdly large duration values (e.g. huge hours/day counts in Float units); a computation upstream produced Infinity (division by zero duration) before conversion; parsing user input without bounds.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/a76b73a1adde20b1. Report an issue: GitHub.