hibernate/hibernate-orm · error · IllegalArgumentException

The string is not a valid string representation of a binary

Error message

The string is not a valid string representation of a binary content.

What it means

PrimitiveByteArrayJavaType.fromString() decodes byte[] from hexadecimal text and requires an even number of characters (two hex digits per byte). Any odd-length string - truncated hex, a stray nibble, values with partial '0x'-style prefixes - is rejected with IllegalArgumentException before parsing starts. This path is used when binary values are materialized from text, e.g. varchar columns on databases lacking a binary type.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java:99

			if ( hexStr.length() == 1 ) {
				appender.append( '0' );
			}
			appender.append( hexStr );
		}
	}

	@Override
	public String extractLoggableRepresentation(byte[] value) {
		return value == null ? super.extractLoggableRepresentation( null ) : Arrays.toString( value );
	}

	@Override
	public byte[] fromString(CharSequence string) {
		if ( string == null ) {
			return null;
		}
		if ( string.length() % 2 != 0 ) {
			throw new IllegalArgumentException( "The string is not a valid string representation of a binary content." );
		}
		byte[] bytes = new byte[string.length() / 2];
		for ( int i = 0; i < bytes.length; i++ ) {
			final String hexStr = string.subSequence( i * 2, (i + 1) * 2 ).toString();
			bytes[i] = (byte) Integer.parseInt( hexStr, 16 );
		}
		return bytes;
	}

	public <X> X unwrap(byte[] value, Class<X> type, WrapperOptions options) {
		if ( value == null ) {
			return null;
		}
		if ( byte[].class.isAssignableFrom( type ) ) {
			return type.cast( value );
		}
		if ( InputStream.class.isAssignableFrom( type ) ) {
			return type.cast( new ByteArrayInputStream( value ) );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Fix the data: hex must have even length; re-export or repair truncated values
  2. Use a real binary column type (VARBINARY, BLOB, RAW) so no hex round-trip occurs
  3. Validate length % 2 == 0 (and [0-9a-fA-F] only) at every write path before persisting
  4. If base64 or prefixed hex is the real format, use an AttributeConverter that decodes it properly

Example fix

// before
UPDATE files SET hash_hex = '0AF'; // odd length
// loading byte[] attribute -> IllegalArgumentException

// after
UPDATE files SET hash_hex = '00AF';
// plus a write-side guard: if (hex.length() % 2 != 0) throw ...
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidHex(byte[] target, CharSequence s) {
    return s != null && s.length() % 2 == 0 && s.chars().allMatch(c -> Character.digit(c, 16) >= 0);
}

if (!isValidHex(null, text)) throw new IllegalArgumentException("Even-length hex string required: " + text);

Type guard

static byte[] tryHexDecode(String s) {
    if (s == null || s.length() % 2 != 0) return null;
    try { return java.util.HexFormat.of().parseHex(s); } catch (Exception e) { return null; }
}

Try / catch

catch (IllegalArgumentException e) {
    if (e.getMessage().contains("binary content"))
        throw new IllegalArgumentException("Hex text must have even length: '" + text + "'", e);
    throw e;
}

Prevention

When it happens

Trigger: A byte[] attribute backed by a text column whose content has odd length (truncated by ETL or hand editing); hex strings with an odd nibble like '0AF'; another writer storing base64 or '0x'-prefixed hex that left a stray character

Common situations: Storing binary as hex on databases without VARBINARY/BLOB support; data cleanup jobs that trimmed characters; integrations that concatenate hex strings incorrectly

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/7a86f818435d4a86. Report an issue: GitHub.