chinabugotech/hutool · error · IllegalArgumentException
invalid hash: {hash}
Error message
invalid hash: {hash} What it means
Thrown by Hashids.decode() after the round-trip integrity check fails: the decoded numbers are re-encoded and if the result does not match the input hash, the hash is considered corrupt or foreign. This guard ensures decode never silently returns garbage values from a tampered or mismatched hash. The hash was either not produced by this Hashids instance (different salt/alphabet) or was altered after generation.
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/codec/Hashids.java:384
}
// shuffle the alphabet
shuffle(currentAlphabet, decodeSalt);
// prepend the decoded value
final long n = translate(block.toString().toCharArray(), currentAlphabet);
decoded = LongStream.concat(decoded, LongStream.of(n));
// create a new block
block = new StringBuilder(length);
}
}
}
// validate the hash
final long[] decodedValue = decoded.toArray();
if (!Objects.equals(hash, encode(decodedValue))) {
throw new IllegalArgumentException("invalid hash: " + hash);
}
return decodedValue;
}
private StringBuilder translate(final long n, final char[] alphabet,
final StringBuilder sb, final int start) {
long input = n;
do {
// prepend the chosen char
sb.insert(start, alphabet[(int) (input % alphabet.length)]);
// trim the input
input = input / alphabet.length;
} while (input > 0);
return sb;
}View on GitHub (pinned to 8870454b2a)
Solutions
- Verify the salt, alphabet, and minLength passed to the Hashids constructor are identical on both the encode and decode sides.
- Catch IllegalArgumentException and treat the input as invalid/untrusted — return a 404 or error response instead of crashing.
- If migrating salt or alphabet, re-encode all stored hashes before switching, or maintain a legacy Hashids instance for old hashes.
- Sanitize user-supplied hash strings before passing to decode — check length and character set against the configured alphabet.
Example fix
// before
Hashids hashids = new Hashids("mysalt".toCharArray(), DEFAULT_ALPHABET, -1);
long[] ids = hashids.decode(userInput); // throws on bad input
// after
Hashids hashids = new Hashids("mysalt".toCharArray(), DEFAULT_ALPHABET, -1);
long[] ids;
try {
ids = hashids.decode(userInput);
} catch (IllegalArgumentException e) {
// treat as not found
ids = null;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate hash charset before decode
boolean valid = hash != null && hash.chars().allMatch(c -> {
char ch = (char) c;
return java.util.Arrays.binarySearch(Hashids.DEFAULT_ALPHABET, ch) >= 0 || "cfhistuCFHISTU".indexOf(ch) >= 0;
}); Try / catch
try {
long[] ids = hashids.decode(hash);
} catch (IllegalArgumentException e) {
// hash is invalid or was produced by a different configuration
logger.warn("Invalid hash decode attempt: {}", hash);
return null; // or throw a domain-specific exception
} Prevention
- Store the salt, alphabet, and minLength configuration alongside hashes to ensure decode compatibility.
- Treat all user-supplied hashes as untrusted input.
- Never change salt or alphabet without a migration plan for existing hashes.
- Add integration tests that encode then decode to verify round-trip integrity.
When it happens
Trigger: Calling hashids.decode("someHash") where the hash was generated by a different Hashids instance using a different salt, alphabet, or minLength. Also triggered by manually editing a hash string, truncating it, or passing a hash from a different library implementation. Calling decodeToHex() with the same invalid input also propagates this error.
Common situations: Salt mismatch between encode and decode sides (e.g., salt loaded from different config files or environment values across services). Upgrading or changing the Hashids alphabet without re-encoding existing stored hashes. Passing a user-supplied ID from a URL parameter that was malformed or spoofed. Using a different Hashids library version that produces different output.
Related errors
- Invalid alphabet for hash
- Incorrect morse.
- invalid number: {number}
- alphabet must contain at least %d unique characters: %d
- alphabet must not contain spaces: index %d
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/d0ac2d6f755af8ae.
Report an issue: GitHub.