{"record":{"id":"c6b4b3039373ba21","repo":"prestodb/presto","slug":"non-direct-byte-buffer-backed-by-byte-array-requir","errorCode":null,"errorMessage":"Non-direct byte buffer backed by byte array required","messagePattern":"Non-direct byte buffer backed by byte array required","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-spark-base/src/main/java/com/facebook/presto/spark/util/PrestoSparkUtils.java","lineNumber":174,"sourceCode":"            {\n                return toIntExact(Zstd.compressBound(uncompressedSize));\n            }\n\n            @Override\n            public int compress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int maxOutputLength)\n            {\n                long size = Zstd.compressByteArray(output, outputOffset, maxOutputLength, input, inputOffset, inputLength, COMPRESSION_LEVEL);\n                if (Zstd.isError(size)) {\n                    throw new RuntimeException(Zstd.getErrorName(size));\n                }\n                return toIntExact(size);\n            }\n\n            @Override\n            public void compress(ByteBuffer input, ByteBuffer output)\n            {\n                if (input.isDirect() || output.isDirect() || !input.hasArray() || !output.hasArray()) {\n                    throw new IllegalArgumentException(\"Non-direct byte buffer backed by byte array required\");\n                }\n                int inputOffset = input.arrayOffset() + input.position();\n                int outputOffset = output.arrayOffset() + output.position();\n\n                int written = compress(input.array(), inputOffset, input.remaining(), output.array(), outputOffset, output.remaining());\n                ((Buffer) output).position(output.position() + written);\n            }\n        };\n    }\n\n    private static PageDecompressor createPageDecompressor()\n    {\n        // based on ZstdJniDecompressor\n        return new PageDecompressor()\n        {\n            @Override\n            public int decompress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int maxOutputLength)\n            {","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-spark-base/src/main/java/com/facebook/presto/spark/util/PrestoSparkUtils.java#L156-L192","documentation":"The Zstd compressor's ByteBuffer overload requires both input and output buffers to be non-direct heap buffers backed by an accessible Java array. It throws IllegalArgumentException when either buffer is direct (off-heap) or lacks a backing array, because it reads/writes via arrayOffset()+position().","triggerScenarios":"Calling PrestoSparkUtils compress with a direct ByteBuffer (allocateDirect) or a read-only/sliced buffer without a backing array for input or output.","commonSituations":"Passing Netty/off-heap buffers or buffers obtained from memory-mapped IO into the compression API; wrapping code that switched from allocate() to allocateDirect(); sliced buffers from larger heap buffers that lost their accessible array.","solutions":["Ensure both ByteBuffers are created with ByteBuffer.allocate (heap, non-direct)","Call hasArray() to verify before compressing; copy direct buffers into heap buffers first","Pass raw byte arrays using the compress(byte[],...) overload instead of ByteBuffers"],"exampleFix":"// before\nByteBuffer input = ByteBuffer.allocateDirect(1024);\ncompressor.compress(input, output);\n// after\nByteBuffer input = ByteBuffer.allocate(1024);\ncompressor.compress(input, output);","handlingStrategy":"validation","validationCode":"if (input.isDirect() || output.isDirect() || !input.hasArray() || !output.hasArray()) { /* copy to heap buffers before compressing */ }","typeGuard":null,"tryCatchPattern":"try { compressor.compress(input, output); } catch (IllegalArgumentException e) { ByteBuffer heapIn = toHeap(input); ByteBuffer heapOut = toHeap(output); compressor.compress(heapIn, heapOut); }","preventionTips":["Always allocate compression buffers with ByteBuffer.allocate, not allocateDirect","Check hasArray() before invoking buffer-based compress","Prefer the byte[] overloads when working with off-heap data"],"tags":["java","compression","zstd","bytebuffer"],"backgroundTag":"direct-bytebuffer-not-supported","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}