{"record":{"id":"952f9352fde9ab06","repo":"alibaba/Sentinel","slug":"bad-byte-array","errorCode":null,"errorMessage":"Bad byte array","messagePattern":"Bad byte array","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/codec/StringDecoder.java","lineNumber":42,"sourceCode":" *\n * @author Eric Zhao\n */\npublic class StringDecoder implements Decoder<String> {\n\n    @Override\n    public boolean canDecode(Class<?> clazz) {\n        return String.class.isAssignableFrom(clazz);\n    }\n\n    @Override\n    public String decode(byte[] bytes) throws Exception {\n        return decode(bytes, Charset.forName(SentinelConfig.charset()));\n    }\n\n    @Override\n    public String decode(byte[] bytes, Charset charset) {\n        if (bytes == null || bytes.length <= 0) {\n            throw new IllegalArgumentException(\"Bad byte array\");\n        }\n        return new String(bytes, charset);\n    }\n}\n","sourceCodeStart":24,"sourceCodeEnd":47,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-transport/sentinel-transport-netty-http/src/main/java/com/alibaba/csp/sentinel/transport/command/codec/StringDecoder.java#L24-L47","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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)","Guard before decoding: if (bytes == null || bytes.length == 0) skip or substitute an empty-string response without the codec","Test custom handlers against empty-input cases in the dashboard command flow"],"exampleFix":"// before (custom handler)\npublic CommandResponse<String> handle(CommandRequest req) {\n    return CommandResponse.ofSuccess(null); // -> StringDecoder throws on empty bytes\n}\n\n// after\npublic CommandResponse<String> handle(CommandRequest req) {\n    String body = computeBody(req);\n    return CommandResponse.ofSuccess(body == null || body.isEmpty() ? \"{}\" : body);\n}","handlingStrategy":"validation","validationCode":"if (bytes == null || bytes.length == 0) {\n    return \"\"; // avoid invoking the decoder on an empty payload\n}\nreturn stringDecoder.decode(bytes, charset);","typeGuard":null,"tryCatchPattern":"try {\n    body = decoder.decode(bytes);\n} catch (IllegalArgumentException e) {\n    body = \"\"; // empty response body instead of encoder failure\n}","preventionTips":["Custom handlers must never return null bodies; return \"[]\" or \"{}\"","Test custom commands against empty-result cases"],"tags":["sentinel","transport","netty","codec","validation"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}