Anuken/Mindustry · error · IllegalArgumentException
Data must be exactly 32 bytes (length: ${data.length})
Error message
Data must be exactly 32 bytes (length: ${data.length}) What it means
DataAssetCache.encodeHash encodes a SHA-256 digest (exactly 32 bytes) into a 52-char unpadded base32 string used as the asset cache key. Passing a byte array of any other length is treated as a programming error and rejected immediately.
Source
Thrown at core/src/mindustry/mod/DataAssetCache.java:53
return hash;
}
public boolean has(String hash){
return get(hash) != null;
}
public synchronized @Nullable Fi get(String shaHash){
if(shaHash == null) return null;
return hashToFile.get(shaHash);
}
public @Nullable Fi get(byte[] shaHash){
return get(encodeHash(shaHash));
}
//base32 without padding; data must be exactly 32 bytes
public static String encodeHash(byte[] data){
if(data.length != 32) throw new IllegalArgumentException("Data must be exactly 32 bytes (length: " + data.length + ")");
char[] out = new char[52];
int di = 0, oi = 0;
for(int i = 0; i < 6; i++){
long bits =
((long)(data[di++] & 0xFF) << 32) |
((long)(data[di++] & 0xFF) << 24) |
((long)(data[di++] & 0xFF) << 16) |
((long)(data[di++] & 0xFF) << 8) |
((long)(data[di++] & 0xFF));
out[oi++] = base32Alphabet[(int)(bits >>> 35) & 0x1F];
out[oi++] = base32Alphabet[(int)(bits >>> 30) & 0x1F];
out[oi++] = base32Alphabet[(int)(bits >>> 25) & 0x1F];
out[oi++] = base32Alphabet[(int)(bits >>> 20) & 0x1F];
out[oi++] = base32Alphabet[(int)(bits >>> 15) & 0x1F];
out[oi++] = base32Alphabet[(int)(bits >>> 10) & 0x1F];
out[oi++] = base32Alphabet[(int)(bits >>> 5) & 0x1F];View on GitHub (pinned to f695ad7e60)
Solutions
- Use SHA-256: MessageDigest.getInstance("SHA-256").digest(...) yields 32 bytes.
- Assert data.length == 32 before calling encodeHash.
- Do not reuse encodeHash for non-SHA-256 digests.
Example fix
// before
byte[] hash = MessageDigest.getInstance("MD5").digest(bytes);
String key = DataAssetCache.encodeHash(hash); // throws: length 16
// after
byte[] hash = MessageDigest.getInstance("SHA-256").digest(bytes);
String key = DataAssetCache.encodeHash(hash); Defensive patterns
Strategy: validation
Validate before calling
// Guarantee a 32-byte digest before encoding.
if(data == null || data.length != 32) {
throw new IllegalArgumentException("SHA-256 hash required (32 bytes), got: " + (data == null ? 0 : data.length));
}
String key = DataAssetCache.encodeHash(data); Type guard
boolean isValidSha256(byte[] d){ return d != null && d.length == 32; } Prevention
- Always produce hashes with SHA-256.
- Never feed digests from other algorithms into encodeHash.
- Add a length assertion in test/build code that exercises hashing.
When it happens
Trigger: encodeHash is called with a hash whose length is not 32 — e.g. MD5 (16), SHA-1 (20), SHA-512 (64), or a truncated/extended buffer.
Common situations: Using the wrong digest algorithm to produce asset hashes; manually constructing hash bytes; corrupted/partial hash from a stream.
Related errors
- Cache file for asset {path} not found!
- Max image size exceeded
- name is null
- Image dimensions are not divisible by 4: {width}x{height}
- Map has no cores!
AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14).
Data as JSON: /api/errors/64238e720aafde9f.
Report an issue: GitHub.