alibaba/nacos · error · IllegalArgumentException

empty payload after enc.

Error message

empty payload after enc.

What it means

NacosAiConfigKeyCodec.decodeSegment received a string that starts with the reserved 'enc.' prefix but has zero characters after it. The encoder produces 'enc.' followed by lowercase hex UTF-8 bytes; an empty payload (just 'enc.' with no hex) is structurally invalid and cannot be decoded.

Source

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

     */
    public static String toPhysicalGroup(String canonicalGroup, String resourcePrefix) {
        return fitToLength(canonicalGroup, MAX_GROUP_LENGTH, resourcePrefix);
    }
    
    /**
     * Decode a segment produced by {@link #encodeSegment(String)}.
     * If not encoded with {@link #ENCODED_PREFIX}, returned unchanged.
     */
    public static String decodeSegment(String encoded) {
        if (encoded == null || encoded.isEmpty()) {
            return encoded;
        }
        if (!encoded.startsWith(ENCODED_PREFIX)) {
            return encoded;
        }
        String hex = encoded.substring(ENCODED_PREFIX.length());
        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);
        }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Do not prepend 'enc.' to empty strings; pass the empty or original value directly to decodeSegment which returns it unchanged.
  2. Audit the data source that produced the malformed segment (database row, config store, serialized JSON).
  3. If the segment is external/untrusted, validate it with hasReservedEncodedPrefix + length check before calling decodeSegment.
  4. Re-encode the original logical value with encodeSegment to regenerate a valid key.

Example fix

// before -- produces 'enc.' with no payload
String key = NacosAiConfigKeyCodec.ENCODED_PREFIX + "";
NacosAiConfigKeyCodec.decodeSegment(key); // throws

// after -- let the encoder decide, or skip encoding for empty
String key = original.isEmpty() ? original
    : NacosAiConfigKeyCodec.encodeSegment(original);
NacosAiConfigKeyCodec.decodeSegment(key); // ok
Defensive patterns

Strategy: validation

Validate before calling

public static String safeDecodeSegment(String encoded) {
    if (encoded == null || encoded.isEmpty()) return encoded;
    if (!encoded.startsWith(NacosAiConfigKeyCodec.ENCODED_PREFIX)) return encoded;
    String hex = encoded.substring(NacosAiConfigKeyCodec.ENCODED_PREFIX.length());
    if (hex.isEmpty()) {
        // corrupted: prefix with no payload — return as-is or re-encode
        return encoded;
    }
    return NacosAiConfigKeyCodec.decodeSegment(encoded);
}

Type guard

public static boolean isValidEncodedSegment(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.matches("[0-9a-fA-F]+") && hex.length() % 2 == 0;
}

Try / catch

try {
    String decoded = NacosAiConfigKeyCodec.decodeSegment(segment);
} catch (IllegalArgumentException e) {
    logger.warn("Malformed encoded segment, using raw value: {}", segment);
    decoded = segment; // or re-encode from source
}

Prevention

When it happens

Trigger: Manually constructing or truncating an encoded key segment to exactly 'enc.'. Passing a corrupted or partially written config dataId/group that was cut off after the prefix. Database or network truncation that stripped the hex portion.

Common situations: A config key was manually edited or programmatically built with an empty encoded segment. A migration or copy operation truncated the dataId. A bug in custom serialization logic that emits 'enc.' for empty strings instead of leaving them unencoded.

Related errors


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