chinabugotech/hutool · error · IllegalArgumentException
Invalid char '{}' at [{}]
Error message
Invalid char '{}' at [{}] What it means
Base58Codec's decoder maps each input char through a lookup table; chars not in the Base58 alphabet (excludes 0, O, I, l and all non-alphanumeric) or any char >= 128 yield digit -1 and an IllegalArgumentException naming the char and index. This is the decode-side input validation, distinct from the checksum check (error 37).
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/codec/Base58Codec.java:137
final int length = alphabet.length();
for (int i = 0; i < length; i++) {
lookupTable[alphabet.charAt(i)] = (byte) i;
}
this.lookupTable = lookupTable;
}
@Override
public byte[] decode(CharSequence encoded) {
if (encoded.length() == 0) {
return new byte[0];
}
// Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits).
final byte[] input58 = new byte[encoded.length()];
for (int i = 0; i < encoded.length(); ++i) {
char c = encoded.charAt(i);
int digit = c < 128 ? lookupTable[c] : -1;
if (digit < 0) {
throw new IllegalArgumentException(StrUtil.format("Invalid char '{}' at [{}]", c, i));
}
input58[i] = (byte) digit;
}
// Count leading zeros.
int zeros = 0;
while (zeros < input58.length && input58[zeros] == 0) {
++zeros;
}
// Convert base-58 digits to base-256 digits.
byte[] decoded = new byte[encoded.length()];
int outputStart = decoded.length;
for (int inputStart = zeros; inputStart < input58.length; ) {
decoded[--outputStart] = divmod(input58, inputStart, 58, 256);
if (input58[inputStart] == 0) {
++inputStart; // optimization - skip leading zeros
}
}
// Ignore extra leading zeroes that were added during the calculation.View on GitHub (pinned to 8870454b2a)
Solutions
- Trim and strip all whitespace before decoding.
- Validate the input matches the Base58 alphabet regex ^[1-9A-HJ-NP-Za-km-z]+$ before calling decode.
- Reject inputs containing the forbidden look-alike chars (0,O,I,l).
Example fix
// before
byte[] d = Base58.decode(" 1BvBMSE YstWetqTFn5\n");
// after
String clean = userInput.trim().replaceAll("\\s", "");
if (!clean.matches("^[1-9A-HJ-NP-Za-km-z]+$")) throw new IllegalArgumentException("bad base58");
byte[] d = Base58.decode(clean); Defensive patterns
Strategy: validation
Validate before calling
String clean = input.trim().replaceAll("\\s", "");
if (!clean.matches("^[1-9A-HJ-NP-Za-km-z]+$")) throw new IllegalArgumentException("invalid base58 char in: " + input); Type guard
static boolean isBase58(String s) { return s != null && s.matches("^[1-9A-HJ-NP-Za-km-z]+$"); } Try / catch
try { return Base58.decode(s); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("bad base58", e); } Prevention
- Trim whitespace and validate the Base58 alphabet (no 0,O,I,l) before decode.
- Do not feed Base64/Base32 strings into a Base58 decoder.
When it happens
Trigger: Decoding a string with whitespace, 0/O/I/l, punctuation, or non-ASCII chars via Base58Codec.decode / Base58.decode. A copy-paste that included spaces or newlines.
Common situations: User-supplied Base58 with formatting whitespace; mistaking Base64/Base32 output for Base58; locale-specific characters in the input.
Related errors
- Illegal hexadecimal character {} at index {}
- Base58 checksum is invalid
- invalid number: {number}
- Error Machine number!
- Bad expression '{}':{}, we find ']' but no '[' !
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/bc26bd07a3b5f6ee.
Report an issue: GitHub.