alibaba/Sentinel · warning · IllegalArgumentException

Bad byte array

Error message

Bad byte array

What it means

StringDecoder is the codec in the netty-http command center that turns response bytes into a String using the configured Sentinel charset (SentinelConfig.charset()). decode(byte[], Charset) rejects null or zero-length byte arrays because new String(emptyBytes, charset) would produce a meaningless empty payload for a command response. It runs on the writeResponse path when encoding handler output.

Source

Thrown at sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/codec/StringDecoder.java:42

 *
 * @author Eric Zhao
 */
public class StringDecoder implements Decoder<String> {

    @Override
    public boolean canDecode(Class<?> clazz) {
        return String.class.isAssignableFrom(clazz);
    }

    @Override
    public String decode(byte[] bytes) throws Exception {
        return decode(bytes, Charset.forName(SentinelConfig.charset()));
    }

    @Override
    public String decode(byte[] bytes, Charset charset) {
        if (bytes == null || bytes.length <= 0) {
            throw new IllegalArgumentException("Bad byte array");
        }
        return new String(bytes, charset);
    }
}

View on GitHub (pinned to a3f40ba8e9)

Solutions

  1. Make the custom CommandHandler always return a non-empty CommandResponse body (e.g. return an empty JSON array or a status string instead of null)
  2. Guard before decoding: if (bytes == null || bytes.length == 0) skip or substitute an empty-string response without the codec
  3. Test custom handlers against empty-input cases in the dashboard command flow

Example fix

// before (custom handler)
public CommandResponse<String> handle(CommandRequest req) {
    return CommandResponse.ofSuccess(null); // -> StringDecoder throws on empty bytes
}

// after
public CommandResponse<String> handle(CommandRequest req) {
    String body = computeBody(req);
    return CommandResponse.ofSuccess(body == null || body.isEmpty() ? "{}" : body);
}
Defensive patterns

Strategy: validation

Validate before calling

if (bytes == null || bytes.length == 0) {
    return ""; // avoid invoking the decoder on an empty payload
}
return stringDecoder.decode(bytes, charset);

Try / catch

try {
    body = decoder.decode(bytes);
} catch (IllegalArgumentException e) {
    body = ""; // empty response body instead of encoder failure
}

Prevention

When it happens

Trigger: A CommandHandler whose handle() returns an empty/absent body (e.g. returns null or an empty model), leading the encoder pipeline to invoke StringDecoder.decode with a null/empty byte array.

Common situations: Custom command handlers returning null or "" for edge-case inputs; modifying a handler so a branch returns nothing; versions where a handler's output for a command (e.g. /getRules variant) can be empty.

Related errors


AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14). Data as JSON: /api/errors/952f9352fde9ab06. Report an issue: GitHub.