{"record":{"id":"82ae4cfca03933b8","repo":"BabylonJS/Babylon.js","slug":"vertex-buffers-pointing-to-the-same-buffer-must-ha","errorCode":null,"errorMessage":"Vertex buffers pointing to the same buffer must have the same byte stride","messagePattern":"Vertex buffers pointing to the same buffer must have the same byte stride","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/serializers/src/glTF/2.0/glTFExporter.ts","lineNumber":1038,"sourceCode":"        }\r\n\r\n        const buffers = Array.from(bufferToVertexBuffersMap.keys());\r\n\r\n        for (const buffer of buffers) {\r\n            const data = buffer.getData();\r\n            if (!data) {\r\n                throw new Error(\"Buffer data is not available\");\r\n            }\r\n\r\n            const vertexBuffers = bufferToVertexBuffersMap.get(buffer);\r\n\r\n            if (!vertexBuffers) {\r\n                continue;\r\n            }\r\n\r\n            const byteStride = vertexBuffers[0].byteStride;\r\n            if (vertexBuffers.some((vertexBuffer) => vertexBuffer.byteStride !== byteStride)) {\r\n                throw new Error(\"Vertex buffers pointing to the same buffer must have the same byte stride\");\r\n            }\r\n\r\n            const bytes = DataArrayToUint8Array(data).slice();\r\n\r\n            // Apply normalizations and color corrections to buffer data in-place.\r\n            for (const vertexBuffer of vertexBuffers) {\r\n                const meshes = vertexBufferToMeshesMap.get(vertexBuffer)!;\r\n                const { byteOffset, byteStride, componentCount, type, count, normalized, kind } = GetVertexBufferInfo(vertexBuffer, meshes);\r\n\r\n                switch (kind) {\r\n                    // Normalize normals and tangents.\r\n                    case VertexBuffer.NormalKind:\r\n                    case VertexBuffer.TangentKind: {\r\n                        EnumerateFloatValues(bytes, byteOffset, byteStride, componentCount, type, count, normalized, (values) => {\r\n                            const length = Math.sqrt(values[0] * values[0] + values[1] * values[1] + values[2] * values[2]);\r\n                            if (length > 0) {\r\n                                const invLength = 1 / length;\r\n                                values[0] *= invLength;\r","sourceCodeStart":1020,"sourceCodeEnd":1056,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/serializers/src/glTF/2.0/glTFExporter.ts#L1020-L1056","documentation":"When several vertex buffers share one underlying Buffer, the exporter must write the raw bytes once and describe each view with a byteStride. If the views referencing the same buffer declare different byteStrides, the single glTF bufferView layout would be ambiguous/incorrect, so the exporter throws instead of emitting a corrupted asset.","triggerScenarios":"Registering multiple VertexBuffers that point to the same Buffer instance but were created with different byteStride values (e.g. interleaved position+uv with stride 20 plus a separately interleaved set with stride 16) and exporting them via GLTFExporter.","commonSituations":"Manual interleaved-vertex-buffer setups where some attributes were packed with different strides; merging meshes whose custom vertex layouts differ; a refactoring that changed stride for one attribute but not others sharing the buffer.","solutions":["Make all vertex buffers sharing the same Buffer use the same byteStride value","Split attributes with a different stride into their own separate Buffer instance so each buffer has a consistent stride","Repack/rebuild the vertex data into a single consistent interleaved layout (or non-interleaved) before exporting","Catch the error and export after normalizing the geometry"],"exampleFix":"// before\nnew VertexBuffer(engine, data, VertexBuffer.PositionKind, true, 0, 20); // stride 20\nnew VertexBuffer(engine, data, VertexBuffer.NormalKind, true, 8, 16);   // stride 16, same buffer\n// after\nnew VertexBuffer(engine, data, VertexBuffer.PositionKind, true, 0, 20);\nnew VertexBuffer(engine, data, VertexBuffer.NormalKind, true, 12, 20);  // same stride 20 on same buffer","handlingStrategy":"validation","validationCode":"function stridesConsistent(bufferToVertexBuffers: Map<IUnknown, IVertexBuffer[]>): boolean {\n    for (const [, vbs] of bufferToVertexBuffers) {\n        const s = vbs[0].byteStride;\n        if (vbs.some((vb) => vb.byteStride !== s)) return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    await GLTF2Export.GLTFAsync(scene, \"scene\");\n} catch (e) {\n    if (e instanceof Error && e.message.startsWith(\"Vertex buffers pointing to the same buffer\")) {\n        // normalize strides and retry export\n    } else { throw e; }\n}","preventionTips":["When building interleaved buffers, derive one shared STRIDE constant and use it for every attribute on that buffer","Group attributes with different strides onto separate Buffer instances","Add a unit test that asserts equal byteStride for all views sharing a buffer before export","Review any custom setVerticesBuffer calls for hardcoded stride values"],"tags":["gltf","export","vertex-buffer","byte-stride","serialization"],"backgroundTag":"inconsistent-buffer-stride","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}