chinabugotech/hutool · error · IllegalArgumentException

Invalid alphabet for hash

Error message

Invalid alphabet for hash

What it means

Thrown during Hashids internal decoding when a character in the hash string is not found in the current alphabet mapping. The translate(char[], char[]) method builds a character-to-index map from the alphabet and throws if a hash character has no entry. This indicates the hash contains characters outside the configured alphabet character set.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/codec/Hashids.java:415

			// trim the input
			input = input / alphabet.length;
		} while (input > 0);

		return sb;
	}

	private long translate(final char[] hash, final char[] alphabet) {
		long number = 0;

		final Map<Character, Integer> alphabetMapping = IntStream.range(0, alphabet.length)
				.mapToObj(idx -> new Object[]{alphabet[idx], idx})
				.collect(Collectors.groupingBy(arr -> (Character) arr[0],
						Collectors.mapping(arr -> (Integer) arr[1],
								Collectors.reducing(null, (a, b) -> a == null ? b : a))));

		for (int i = 0; i < hash.length; ++i) {
			number += alphabetMapping.computeIfAbsent(hash[i], k -> {
				throw new IllegalArgumentException("Invalid alphabet for hash");
			}) * (long) Math.pow(alphabet.length, hash.length - i - 1);
		}

		return number;
	}

	private char[] deriveNewAlphabet(final char[] alphabet, final char[] salt, final char lottery) {
		// create the new salt
		final char[] newSalt = new char[alphabet.length];

		// 1. lottery
		newSalt[0] = lottery;
		int spaceLeft = newSalt.length - 1;
		int offset = 1;
		// 2. salt
		if (salt.length > 0 && spaceLeft > 0) {
			int length = Math.min(salt.length, spaceLeft);
			System.arraycopy(salt, 0, newSalt, offset, length);

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Ensure the hash being decoded was produced by a Hashids instance with the same alphabet configuration.
  2. Validate that the input string contains only characters from the expected alphabet and guard characters before calling decode.
  3. Catch IllegalArgumentException around the decode call and handle invalid input gracefully.
  4. Check for URL-encoding or HTML-encoding issues that may have altered the hash string before it reached decode().

Example fix

// before
long[] ids = hashids.decode(userInput); // throws if char not in alphabet

// after
Set<Character> valid = new HashSet<>();
for (char c : "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") valid.add(c);
boolean allValid = userInput.chars().allMatch(c -> valid.contains((char)c));
long[] ids = allValid ? hashids.decode(userInput) : null;
Defensive patterns

Strategy: try-catch

Validate before calling

// Check all hash chars are in the alphabet before decode
Set<Character> alphabetChars = new HashSet<>();
for (char c : hashidsAlphabet) alphabetChars.add(c);
boolean allValid = hash.chars().allMatch(c -> alphabetChars.contains((char) c));

Try / catch

try {
    long[] ids = hashids.decode(hash);
} catch (IllegalArgumentException e) {
    // hash contains chars not in alphabet, or round-trip failed
    return null;
}

Prevention

When it happens

Trigger: Decoding a hash string that contains characters not present in the Hashids instance's filtered alphabet. This can happen when a hash from a different Hashids configuration (with a different alphabet) is decoded, or when the hash string has been corrupted with foreign characters. The error originates inside decode() at the translate call on line 372 and surfaces before the round-trip validation on line 383.

Common situations: Mixing hashes from different Hashids instances with custom alphabets. Passing arbitrary strings (URL slugs, UUIDs) to decode() that were never Hashids-encoded. Character encoding issues where the hash string is mangled in transit (e.g., URL-decoded incorrectly).

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/a6eac6907247631f. Report an issue: GitHub.