apple/pkl · error

cannotConvertLargeFloat

cannotConvertLargeFloat

Error message

cannotConvertLargeFloat / cannotConvertNonFiniteFloat

What it means

Thrown when the double-precision truncating division (`~/` on Float operands) produces a quotient that cannot be represented as a 64-bit Long: either a finite result too large (cannotConvertLargeFloat) or a non-finite result such as Infinity/NaN (cannotConvertNonFiniteFloat). MathUtils.roundToLong throws ArithmeticException in both cases.

Solutions

  1. Check the divisor is non-zero before Float truncating division
  2. Validate Float operands are finite and the quotient fits in Int range
  3. Perform the division in Float and convert with an explicit range check
  4. Fix upstream computations that produce NaN/Infinity

Example fix

// before
parts = total ~/ stepSize // stepSize == 0.0
// after
parts = if (stepSize == 0.0) 0 else total ~/ stepSize
Defensive patterns

Strategy: validation

Validate before calling

function safeFloatTruncDiv(x, y) { return (y === 0 || !Number.isFinite(x / y)) ? 0 : x / y }

Type guard

function isConvertibleToLong(q) { return Number.isFinite(q) && Math.abs(q) <= 9223372036854775807 }

Prevention

When it happens

Trigger: Evaluating `left ~/ right` where either operand is a Float and `x / y` overflows Long range, or is Infinity/NaN (e.g. division by 0.0, or infinite operand).

Common situations: Dividing by a Float zero, operating on huge Float config values, NaN propagating from an earlier Float computation.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/binary/TruncatingDivisionNode.java:117

  }

  @Specialization
  protected long eval(VmDataSize left, VmDataSize right) {
    // use same conversion strategy as add/subtract
    if (left.getUnit().ordinal() <= right.getUnit().ordinal()) {
      var leftValue = left.convertTo(right.getUnit()).getValue();
      return doTruncatingDivide(leftValue, right.getValue());
    }
    var rightValue = right.convertTo(left.getUnit()).getValue();
    return doTruncatingDivide(left.getValue(), rightValue);
  }

  private long doTruncatingDivide(double x, double y) {
    try {
      return MathUtils.roundToLong(x / y, RoundingMode.DOWN);
    } catch (ArithmeticException e) {
      CompilerDirectives.transferToInterpreter();
      throw exceptionBuilder()
          .evalError(
              Double.isFinite(x) ? "cannotConvertLargeFloat" : "cannotConvertNonFiniteFloat",
              new ProgramValue("Float", x))
          .build();
    }
  }
}

View on GitHub (pinned to f3efcbfc9b)