{"record":{"id":"b106cdbe62afec71","repo":"libgdx/libgdx","slug":"dst-must-be-a-bytebuffer","errorCode":null,"errorMessage":"dst must be a ByteBuffer","messagePattern":"dst must be a ByteBuffer","errorType":"exception","errorClass":"GdxRuntimeException","httpStatus":null,"severity":"error","filePath":"backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/BufferUtils.java","lineNumber":70,"sourceCode":"\t\tfloatBuffer.put(src, offset, numFloats);\n\t\tdst.position(0);\n\t\tif (dst instanceof ByteBuffer)\n\t\t\tdst.limit(numFloats << 2);\n\t\telse\n\t\t\tdst.limit(numFloats);\n\t}\n\n\t/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer}\n\t * instance's {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same,\n\t * the limit will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error\n\t * checking is performed</b>.\n\t * \n\t * @param src the source array.\n\t * @param srcOffset the offset into the source array.\n\t * @param dst the destination Buffer, its position is used as an offset.\n\t * @param numElements the number of elements to copy. */\n\tpublic static void copy (byte[] src, int srcOffset, Buffer dst, int numElements) {\n\t\tif (!(dst instanceof ByteBuffer)) throw new GdxRuntimeException(\"dst must be a ByteBuffer\");\n\n\t\tByteBuffer byteBuffer = (ByteBuffer)dst;\n\t\tint oldPosition = byteBuffer.position();\n\t\tbyteBuffer.limit(oldPosition + numElements);\n\t\tbyteBuffer.put(src, srcOffset, numElements);\n\t\tbyteBuffer.position(oldPosition);\n\t}\n\n\t/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer}\n\t * instance's {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same,\n\t * the limit will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error\n\t * checking is performed</b>.\n\t * \n\t * @param src the source array.\n\t * @param srcOffset the offset into the source array.\n\t * @param dst the destination Buffer, its position is used as an offset.\n\t * @param numElements the number of elements to copy. */\n\tpublic static void copy (short[] src, int srcOffset, Buffer dst, int numElements) {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/libgdx/libgdx/blob/97f40861878058087be0685ca167ddfde132134b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/BufferUtils.java#L52-L88","documentation":"BufferUtils.copy(byte[] src, int srcOffset, Buffer dst, int numElements) requires dst to be a ByteBuffer because byte copies go straight through ByteBuffer.put — there is no typed view to convert through. Any other Buffer subclass (IntBuffer, FloatBuffer, ...) fails the instanceof check and throws. The overloads for short/char/int/long/double accept ByteBuffer or their typed buffer, but the byte variant is ByteBuffer-only.","triggerScenarios":"Passing a FloatBuffer/IntBuffer as dst when copying a byte[]; generic buffer-fill helper code that treats all copy overloads uniformly; copying raw vertex bytes into a mesh's typed FloatBuffer.","commonSituations":"Writing serialization/network code that unpacks bytes into typed buffers via copy() instead of view buffers; refactoring code from copyVBO/other BufferUtils APIs where ByteBuffer was always the receiver; porting desktop NIO code to the GWT emulated BufferUtils with mismatched buffer types.","solutions":["Copy bytes into a ByteBuffer dst; if you need them as floats, get a view: byteDst.asFloatBuffer().put(...) or read via asFloatBuffer().","If your data is already float[], use copy(float[], int, Buffer, int) which accepts a FloatBuffer dst.","Allocate dst with BufferUtils.newByteBuffer(...) and convert after the copy."],"exampleFix":"// before\nFloatBuffer fb = BufferUtils.newFloatBuffer(bytes.length / 4);\nBufferUtils.copy(bytes, 0, fb, bytes.length); // throws: dst must be a ByteBuffer\n\n// after\nByteBuffer bb = BufferUtils.newByteBuffer(bytes.length);\nBufferUtils.copy(bytes, 0, bb, bytes.length);\nbb.position(0);\nFloatBuffer fb = bb.asFloatBuffer();","handlingStrategy":"type-guard","validationCode":"if (!(dst instanceof ByteBuffer)) {\n    throw new IllegalArgumentException(\"dst must be ByteBuffer for byte[] copy\");\n}\nBufferUtils.copy(bytes, 0, dst, bytes.length);","typeGuard":"boolean acceptsByteArray(Buffer b) { return b instanceof ByteBuffer; }","tryCatchPattern":null,"preventionTips":["Reserve ByteBuffer for byte[] copies; use typed views afterwards.","Wrap BufferUtils.copy in project helpers that fix src/dst type pairs."],"tags":["libgdx","buffer","type-mismatch","copy","api-contract"],"backgroundTag":null,"analyzedSha":"97f40861878058087be0685ca167ddfde132134b","analyzedAt":"2026-08-14T10:52:53.492Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}