alibaba/nacos · error · IllegalArgumentException

illegal hex length: {len}

Error message

illegal hex length: {len}

What it means

NacosAiConfigKeyCodec.fromHex received a hex string whose length is odd. Every byte requires two hex characters, so an odd-length hex payload is structurally invalid and cannot be decoded into bytes.

Source

Thrown at api/src/main/java/com/alibaba/nacos/api/ai/model/NacosAiConfigKeyCodec.java:192

        if (hex.isEmpty()) {
            throw new IllegalArgumentException("empty payload after " + ENCODED_PREFIX);
        }
        return new String(fromHex(hex), StandardCharsets.UTF_8);
    }
    
    private static String toHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            sb.append(Character.forDigit((b >> 4) & 0xF, 16));
            sb.append(Character.forDigit(b & 0xF, 16));
        }
        return sb.toString();
    }
    
    private static byte[] fromHex(String hex) {
        int len = hex.length();
        if ((len & 1) != 0) {
            throw new IllegalArgumentException("illegal hex length: " + len);
        }
        byte[] out = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            int hi = Character.digit(hex.charAt(i), 16);
            int lo = Character.digit(hex.charAt(i + 1), 16);
            if (hi < 0 || lo < 0) {
                throw new IllegalArgumentException("illegal hex at index " + i);
            }
            out[i / 2] = (byte) ((hi << 4) + lo);
        }
        return out;
    }
    
    private static boolean hasReservedEncodedPrefix(String value) {
        return value.regionMatches(true, 0, ENCODED_PREFIX, 0, ENCODED_PREFIX.length());
    }
    
    private static String fitToLength(String candidate, int maxLength, String preservedPrefix) {

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Re-encode the original logical value with encodeSegment to produce a correct even-length hex string.
  2. Inspect the stored segment byte-by-byte to find where truncation occurred.
  3. Add a pre-check: if (hex.length() % 2 != 0) reject or re-encode before calling decodeSegment.
  4. Check the database schema column length against the maximum encoded segment size.

Example fix

// before
String bad = "enc.0a1"; // odd length
NacosAiConfigKeyCodec.decodeSegment(bad);

// after -- re-encode from source of truth
String good = NacosAiConfigKeyCodec.encodeSegment(originalValue);
NacosAiConfigKeyCodec.decodeSegment(good);
Defensive patterns

Strategy: validation

Validate before calling

public static boolean isValidHex(String hex) {
    return hex != null && hex.length() % 2 == 0 && hex.matches("[0-9a-fA-F]+");
}

Type guard

public static boolean isDecodableSegment(String s) {
    if (s == null || s.isEmpty()) return true;
    if (!s.startsWith(NacosAiConfigKeyCodec.ENCODED_PREFIX)) return true;
    String hex = s.substring(NacosAiConfigKeyCodec.ENCODED_PREFIX.length());
    return !hex.isEmpty() && hex.length() % 2 == 0 && hex.matches("[0-9a-fA-F]+");
}

Try / catch

try {
    String decoded = NacosAiConfigKeyCodec.decodeSegment(segment);
} catch (IllegalArgumentException e) {
    // segment is corrupted; re-encode from canonical source or skip
    decoded = reEncodeFromSource(segment);
}

Prevention

When it happens

Trigger: An encoded segment ('enc.' + hex) was truncated by one character. A custom or external process generated a partial hex string. Character encoding mismatch or copy-paste dropped a trailing nibble.

Common situations: Database column truncation (e.g. VARCHAR length off by one). Manual editing of a stored config key. A bug in a serialization layer that strips whitespace or control characters from hex output.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/02f6a7648449de3b. Report an issue: GitHub.