apache/hadoop · error · RuntimeException

Not a hex character: {c}

Error message

Not a hex character: {c}

What it means

Thrown by MD5Hash.charToNibble(char) when a character in the supposed hex string is not 0-9, a-f, or A-F. setDigest() walks the string two characters per byte; any stray character (g-z, symbols, whitespace, '0x' prefix) hits this RuntimeException. It means the input was never valid hex, independent of length — the length check in setDigest passed but the content check failed.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/MD5Hash.java:303

      throw new IllegalArgumentException("Wrong length: " + hex.length());
    byte[] digest = new byte[MD5_LEN];
    for (int i = 0; i < MD5_LEN; i++) {
      int j = i << 1;
      digest[i] = (byte)(charToNibble(hex.charAt(j)) << 4 |
                         charToNibble(hex.charAt(j+1)));
    }
    this.digest = digest;
  }

  private static final int charToNibble(char c) {
    if (c >= '0' && c <= '9') {
      return c - '0';
    } else if (c >= 'a' && c <= 'f') {
      return 0xa + (c - 'a');
    } else if (c >= 'A' && c <= 'F') {
      return 0xA + (c - 'A');
    } else {
      throw new RuntimeException("Not a hex character: " + c);
    }
  }


}

View on GitHub (pinned to 2add963021)

Solutions

  1. Pre-validate with a regex (^[0-9a-fA-F]{32}$) and reject with a descriptive error naming the offending input.
  2. Strip non-hex noise before parsing: trim whitespace, remove a leading '0x', split off anything after whitespace.
  3. If the file is genuinely corrupted, regenerate the checksum instead of trying to parse it.

Example fix

// before: prefixed value blows up inside charToNibble
new MD5Hash("0x" + hex32);

// after: strict pre-validation with a useful error
if (!hex32.matches("[0-9a-fA-F]{32}")) {
  throw new IllegalArgumentException("Not an MD5 hex string: '" + hex32 + "'");
}
new MD5Hash(hex32);
Defensive patterns

Strategy: validation

Validate before calling

if (!hex.matches("[0-9a-fA-F]{32}")) {
  throw new IllegalArgumentException(
      "Invalid MD5 hex '" + hex + "' — must be exactly 32 hex chars");
}
md5.setDigest(hex);

Type guard

static boolean isHexNibbleString(String s) {
  return s != null && s.matches("[0-9a-fA-F]*") && (s.length() % 2) == 0;
}

Prevention

When it happens

Trigger: setDigest("0x" + hash) or a hash prefixed/suffixed with junk; a checksum line containing the filename because it wasn't split; whitespace or quotes embedded in the string; corrupted checksum files where a byte was replaced by a non-hex character.

Common situations: Parsing user-maintained checksum manifests; values read from properties files that still contain quoting; concatenation bugs that glue a path onto the hash; locale/case transformations that insert separators.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/5569704904e64eaf. Report an issue: GitHub.