bazelbuild/bazel · error · NumberFormatException
invalid base-%d literal: %s
Error message
invalid base-%d literal: %s
What it means
StarlarkInt.parse's parse-failure error: it is raised in two places — first when, after stripping one leading sign and any 0x/0o/0b prefix, the digit string still starts with '+' or '-' (Long.parseLong/BigInteger must not see an embedded second sign), and again when neither Long.parseLong nor BigInteger can parse the digits in the requested base. The message includes the base and the repr of the original input.
Source
Thrown at src/main/java/net/starlark/java/eval/StarlarkInt.java:159
// No prefix, no base? Use decimal.
if (digits == s && base == 0) {
// Don't infer base when input starts with '0' due to octal/decimal ambiguity.
if (s.length() > 1 && s.charAt(0) == '0') {
throw new NumberFormatException(
"cannot infer base when string begins with a 0: "
+ Starlark.repr(stringForErrors, StarlarkSemantics.DEFAULT));
}
base = 10;
}
if (base < 2 || base > 36) {
throw new NumberFormatException(
String.format("invalid base %d (want 2 <= base <= 36)", base));
}
// Do not allow Long.parseLong and new BigInteger to accept another +/- sign.
if (digits.startsWith("+") || digits.startsWith("-")) {
throw new NumberFormatException(
String.format(
"invalid base-%d literal: %s",
base, Starlark.repr(stringForErrors, StarlarkSemantics.DEFAULT)));
}
StarlarkInt result;
try {
result = StarlarkInt.of(Long.parseLong(digits, base));
} catch (NumberFormatException unused1) {
try {
result = StarlarkInt.of(new BigInteger(digits, base));
} catch (NumberFormatException unused2) {
throw new NumberFormatException(
String.format(
"invalid base-%d literal: %s",
base, Starlark.repr(stringForErrors, StarlarkSemantics.DEFAULT)));
}
}View on GitHub (pinned to e6e199d060)
Solutions
- Normalize input before parsing: strip whitespace, collapse duplicate signs, remove separators: s = s.replace("_", "").strip().
- Apply the sign yourself: int(s.lstrip("+-"), base) * (-1 if s.startswith("-") else 1).
- Check the digit alphabet matches the base (base 8 has no 8/9; base 16 allows a-f) and remove 0x/0o/0b when passing an explicit base.
Example fix
# before
n = int(raw, 16) # raw = "-0xff" or "0xff" with base given is fine, but "ff_00" or " -0xff" fails
# after
clean = raw.strip().replace("_", "")
n = int(clean, 16) Defensive patterns
Strategy: validation
Validate before calling
import re # where available; otherwise manual scan
def looks_like_int(s, base=10):
s = s.strip().replace("_", "")
return re.match(r"^[+-]?(0[xob])?[0-9a-zA-Z]+$", s) != None # then also check digits < base Prevention
- Normalize before parsing: strip whitespace, remove '_' separators, collapse signs.
- With an explicit base, drop 0x/0o/0b prefixes and any leading +/- and reapply the sign yourself.
- Whitelist the digit alphabet for the base (e.g. no 8/9 in base 8).
When it happens
Trigger: int("--5"), int("+-3"), int("0x-10", 16) (sign after prefix), int("abc", 10), int("129", 8) (digit 9 invalid in base 8), int("1_000") (underscores unsupported), int(" "+"5") — whitespace not stripped.
Common situations: Parsing numbers with sign conventions the parser disallows (double negatives for 'minus a negative'); digit separators like 1_000 copied from Java/Python 3.6; hex strings with 0x prefix plus explicit base 16 AND a sign in the wrong place; whitespace or units left in the string ("5px", " 5").
Related errors
- empty string
- cannot infer base when string begins with a 0: %s
- invalid base %d (want 2 <= base <= 36)
- This converter doesn't support Starlark reversal.
- Invalid options syntax: %s Note: Negative target patterns ca
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/687947411c3e209e.
Report an issue: GitHub.