{"record":{"id":"a18aca425986df0a","repo":"libgdx/libgdx","slug":"cannot-change-attributes-while-vbo-is-bound","errorCode":null,"errorMessage":"Cannot change attributes while VBO is bound","messagePattern":"Cannot change attributes while VBO is bound","errorType":"exception","errorClass":"GdxRuntimeException","httpStatus":null,"severity":"error","filePath":"backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/graphics/glutils/InstanceBufferObject.java","lineNumber":96,"sourceCode":"\t@Deprecated\n\tpublic FloatBuffer getBuffer () {\n\t\tisDirty = true;\n\t\treturn buffer;\n\t}\n\n\t@Override\n\tpublic FloatBuffer getBuffer (boolean forWriting) {\n\t\tisDirty |= forWriting;\n\t\treturn buffer;\n\t}\n\n\t/** Low level method to reset the buffer and attributes to the specified values. Use with care!\n\t *\n\t * @param data\n\t * @param ownsBuffer\n\t * @param value */\n\tprotected void setBuffer (Buffer data, boolean ownsBuffer, VertexAttributes value) {\n\t\tif (isBound) throw new GdxRuntimeException(\"Cannot change attributes while VBO is bound\");\n\t\tattributes = value;\n\t\tif (data instanceof ByteBuffer)\n\t\t\tbyteBuffer = (ByteBuffer)data;\n\t\telse\n\t\t\tthrow new GdxRuntimeException(\"Only ByteBuffer is currently supported\");\n\t\tthis.ownsBuffer = ownsBuffer;\n\n\t\tfinal int l = byteBuffer.limit();\n\t\tbyteBuffer.limit(byteBuffer.capacity());\n\t\tbuffer = byteBuffer.asFloatBuffer();\n\t\tbyteBuffer.limit(l);\n\t\tbuffer.limit(l / 4);\n\t}\n\n\tprivate void bufferChanged () {\n\t\tif (isBound) {\n\t\t\tGdx.gl20.glBufferData(GL20.GL_ARRAY_BUFFER, byteBuffer.limit(), null, usage);\n\t\t\tGdx.gl20.glBufferData(GL20.GL_ARRAY_BUFFER, byteBuffer.limit(), byteBuffer, usage);","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/libgdx/libgdx/blob/97f40861878058087be0685ca167ddfde132134b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/graphics/glutils/InstanceBufferObject.java#L78-L114","documentation":"setBuffer() swaps the underlying ByteBuffer and VertexAttributes of an InstanceBufferObject. Doing this while the buffer is bound to GL state (isBound == true, set by bind() and cleared by unbind()) would desynchronize the CPU-side view from what the shader attribute pointers were set up against, so the method fail-fasts. This mirrors the same guard in VertexBufferObject.","triggerScenarios":"Calling setBuffer(...) between bind(shader) and unbind(); reconfiguring attributes from inside a render callback while the instance buffer is bound; a reassign method invoked during a batched draw loop before unbind() ran.","commonSituations":"Hot-swapping instance attributes (e.g. particle systems changing attribute layout) without unbinding first; refactoring a Mesh-style class so that buffer resets happen mid-draw; forgetting unbind() after an exception interrupted a draw sequence, leaving isBound latched true.","solutions":["Always pair bind()/unbind(): call unbind() (or ensure the drawing API you used ends with it) before calling setBuffer().","Restructure so attribute-layout changes happen at frame boundaries, not during rendering.","If an exception can interrupt a draw, catch it and unbind() in a finally block so isBound resets."],"exampleFix":"// before\ninstanceBuffer.bind(shader);\ninstanceBuffer.setBuffer(newData, true, newAttributes); // throws: isBound\ninstanceBuffer.unbind();\n\n// after\ninstanceBuffer.unbind();\ninstanceBuffer.setBuffer(newData, true, newAttributes);\ninstanceBuffer.bind(shader);","handlingStrategy":"validation","validationCode":"// Call setBuffer only when unbound; enforce with your own wrapper:\nvoid reconfigure(InstanceBufferObject ibo, ByteBuffer data, VertexAttributes attrs) {\n    ibo.unbind(); // no-op safe when not bound in newer versions; else track state\n    ibo.setBuffer(data, true, attrs);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pair every bind() with unbind(), especially on exception paths (finally).","Change buffer layouts at frame boundaries only."],"tags":["libgdx","gwt","instancing","vbo","state-machine","lifecycle"],"backgroundTag":null,"analyzedSha":"97f40861878058087be0685ca167ddfde132134b","analyzedAt":"2026-08-14T10:52:53.492Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}