bazelbuild/bazel · error · MissingFormatWidthException

got %s for '%%%c' format, want int or float

Error message

got %s for '%%%c' format, want int or float

What it means

Thrown by %d/%o/%x/%X formatting when the argument is neither int nor float — the switch over the argument's runtime type falls through to the default branch. The message interpolates the actual Starlark type name and the conversion character, e.g. got string for '%d' format, want int or float.

Source

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

      }
      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();
                case StarlarkFloat starlarkFloat -> starlarkFloat.toDouble();
                default ->
                    throw new MissingFormatWidthException(
                        String.format(

View on GitHub (pinned to e6e199d060)

Solutions

  1. Convert explicitly before formatting: "%d" % int(s) (guard the conversion if the string may be non-numeric).
  2. Use %s if you just want the value rendered.
  3. Default optional values to 0 rather than None when they feed %d.

Example fix

# before
"retry %d" % attempt  # attempt is "3"

# after
"retry %d" % int(attempt)
Defensive patterns

Strategy: type-guard

Type guard

def is_number(v):
    return type(v) in ("int", "float")

assert is_number(v), "%%d needs int/float, got %s" % type(v)

Prevention

When it happens

Trigger: "%d" % "12", "%x" % [255], "%d" % None, "%o" % depset([1]) — any non-numeric argument to an integer conversion.

Common situations: Values read from labels, environment strings, or structured data are strings and are formatted as if numeric; None defaults flowing into a count field; forgetting that %-formatting does not coerce types.

Related errors


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