bazelbuild/bazel · error · MissingFormatWidthException

got %s, want a finite number

Error message

got %s, want a finite number

What it means

Thrown by %d/%o/%x/%X formatting when the argument is a StarlarkFloat that is infinite or NaN. The printer tries StarlarkInt.ofFiniteDouble to coerce the float to an integer; ofFiniteDouble rejects non-finite/non-integral-representable doubles with IllegalArgumentException, which is converted to this MissingFormatWidthException.

Source

Thrown at src/main/java/net/starlark/java/eval/Printer.java:433

            "not enough arguments for format pattern "
                + Starlark.repr(pattern, semantics)
                + ": "
                + Starlark.repr(Tuple.copyOf(arguments), semantics));
      }
      Object arg = arguments.get(a++);

      switch (conv) {
        case 'd', 'o', 'x', 'X' -> {
          Number n =
              switch (arg) {
                case StarlarkInt starlarkInt -> starlarkInt.toNumber();
                case Integer integer -> integer;
                case StarlarkFloat starlarkFloat -> {
                  double d = starlarkFloat.toDouble();
                  try {
                    yield StarlarkInt.ofFiniteDouble(d).toNumber();
                  } catch (IllegalArgumentException unused) {
                    throw new MissingFormatWidthException("got " + arg + ", want a finite number");
                  }
                }
                default ->
                    throw new MissingFormatWidthException(
                        String.format(
                            "got %s for '%%%c' format, want int or float",
                            Starlark.type(arg), conv));
              };
          printer.append(
              String.format(
                  conv == 'd' ? "%d" : conv == 'o' ? "%o" : conv == 'x' ? "%x" : "%X", n));
        }

        case 'e', 'f', 'g', 'E', 'F', 'G' -> {
          double v =
              switch (arg) {
                case Integer integer -> (double) integer;
                case StarlarkInt starlarkInt -> starlarkInt.toDouble();

View on GitHub (pinned to e6e199d060)

Solutions

  1. Use a float conversion (%f/%g/%e) instead of %d for non-integral or possibly non-finite values.
  2. Sanitize before formatting: replace non-finite values (v == v and abs(v) != float("inf")) with 0 or a sentinel.
  3. Fix the upstream computation that produced inf/nan (guard divisors, check for zero denominators).

Example fix

# before
"%d items" % (total / count)  # count can be 0 -> inf/nan

# after
"%g items" % (total / count) if count else "n/a"
Defensive patterns

Strategy: validation

Validate before calling

def finite_int(v):
    if type(v) == "float" and (v != v or v == float("inf") or v == float("-inf")):
        fail("non-finite value for %d: %s" % (type(v), v))
    return v

"%d" % finite_int(x)

Type guard

def is_finite_number(v):
    return type(v) == "int" or (type(v) == "float" and v == v and v != float("inf") and v != float("-inf"))

Prevention

When it happens

Trigger: "%d" % float("inf"), "%x" % float("nan"), "%d" % (1e300 / 1e300 * float('nan')), or any arithmetic that yields inf/nan (division overflows, float("1e400")) followed by %d formatting.

Common situations: Formatting computed ratios or scores that can divide by zero; parsing user input like 'inf'/'nan' with float(); JSON-decoded floats carrying NaN before %d logging.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/06c4a727f9292b27. Report an issue: GitHub.