chinabugotech/hutool · error · IllegalArgumentException
alphabet must contain at least %d unique characters: %d
Error message
alphabet must contain at least %d unique characters: %d
What it means
Thrown during Hashids construction in validateAndFilterAlphabet() when the custom alphabet array has fewer than MIN_ALPHABET_LENGTH (16) characters. The Hashids algorithm requires a minimum alphabet size of 16 to function correctly. This is a hard requirement enforced at object creation time, not at encode/decode time.
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/codec/Hashids.java:449
if (salt.length > 0 && spaceLeft > 0) {
int length = Math.min(salt.length, spaceLeft);
System.arraycopy(salt, 0, newSalt, offset, length);
spaceLeft -= length;
offset += length;
}
// 3. alphabet
if (spaceLeft > 0) {
System.arraycopy(alphabet, 0, newSalt, offset, spaceLeft);
}
// shuffle
return shuffle(alphabet, newSalt);
}
private char[] validateAndFilterAlphabet(final char[] alphabet, final char[] separators) {
// validate size
if (alphabet.length < MIN_ALPHABET_LENGTH) {
throw new IllegalArgumentException(String.format("alphabet must contain at least %d unique " +
"characters: %d", MIN_ALPHABET_LENGTH, alphabet.length));
}
final Set<Character> seen = new LinkedHashSet<>(alphabet.length);
final Set<Character> invalid = IntStream.range(0, separators.length)
.mapToObj(idx -> separators[idx])
.collect(Collectors.toSet());
// add to seen set (without duplicates)
IntStream.range(0, alphabet.length)
.forEach(i -> {
if (alphabet[i] == ' ') {
throw new IllegalArgumentException(String.format("alphabet must not contain spaces: " +
"index %d", i));
}
final Character c = alphabet[i];
if (!invalid.contains(c)) {
seen.add(c);View on GitHub (pinned to 8870454b2a)
Solutions
- Ensure the custom alphabet array contains at least 16 unique characters.
- Use the default DEFAULT_ALPHABET (62 characters) if you do not have a specific requirement for a custom alphabet.
- Add a unit test or startup assertion that checks the alphabet length before constructing the Hashids instance.
Example fix
// before
char[] alphabet = "0123456789abcdef".toCharArray(); // 16 chars — OK
Hashids h = new Hashids(salt, alphabet, -1);
char[] tooShort = "0123456789".toCharArray(); // 10 chars — throws
Hashids h2 = new Hashids(salt, tooShort, -1);
// after — always verify length
char[] alphabet = "0123456789abcdef".toCharArray();
if (alphabet.length < 16) throw new IllegalStateException("alphabet too short");
Hashids h = new Hashids(salt, alphabet, -1); Defensive patterns
Strategy: validation
Validate before calling
if (alphabet.length < 16) {
throw new IllegalStateException("Alphabet must have at least 16 characters, got: " + alphabet.length);
} Prevention
- Use the default DEFAULT_ALPHABET unless you have a specific reason for a custom one.
- Add a startup check or unit test validating the alphabet length.
- Document the minimum alphabet size requirement in your configuration.
When it happens
Trigger: Calling new Hashids(salt, customAlphabet, minLength) or Hashids.create(salt, customAlphabet, minLength) where customAlphabet has fewer than 16 characters (before deduplication and separator filtering). Note the check uses the raw array length, not the post-deduplication unique count.
Common situations: Defining a custom alphabet that is too short for a specialized use case. Accidentally truncating the alphabet array in configuration. Copy-paste errors when defining the alphabet constant.
Related errors
- alphabet must not contain spaces: index %d
- Invalid alphabet for hash
- invalid number: {number}
- invalid hash: {hash}
- Unsupported model:
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/c555c646d11ba319.
Report an issue: GitHub.