{"record":{"id":"b716f21715268c9f","repo":"BabylonJS/Babylon.js","slug":"output-length-is-not-valid","errorCode":null,"errorMessage":"Output length is not valid","messagePattern":"Output length is not valid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Buffers/bufferUtils.ts","lineNumber":411,"sourceCode":" * @param normalized whether the data is normalized\r\n * @param totalVertices number of vertices in the buffer to take into account\r\n * @param output the output float array\r\n */\r\nexport function CopyFloatData(\r\n    input: DataArray,\r\n    size: number,\r\n    type: number,\r\n    byteOffset: number,\r\n    byteStride: number,\r\n    normalized: boolean,\r\n    totalVertices: number,\r\n    output: Float32Array\r\n): void {\r\n    const tightlyPackedByteStride = size * GetTypeByteLength(type);\r\n    const count = totalVertices * size;\r\n\r\n    if (output.length !== count) {\r\n        throw new Error(\"Output length is not valid\");\r\n    }\r\n\r\n    if (type !== Constants.FLOAT || byteStride !== tightlyPackedByteStride) {\r\n        EnumerateFloatValues(input, byteOffset, byteStride, size, type, count, normalized, (values, index) => {\r\n            for (let i = 0; i < size; i++) {\r\n                output[index + i] = values[i];\r\n            }\r\n        });\r\n        return;\r\n    }\r\n\r\n    if (input instanceof Array) {\r\n        const offset = byteOffset / 4;\r\n        output.set(input, offset);\r\n    } else if (ArrayBuffer.isView(input)) {\r\n        const offset = input.byteOffset + byteOffset;\r\n        if ((offset & 3) !== 0) {\r\n            Logger.Warn(\"Float array must be aligned to 4-bytes border\");\r","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Buffers/bufferUtils.ts#L393-L429","documentation":"BufferUtils.CopyFloatData throws \"Output length is not valid\" when output.length !== totalVertices * size, where count is the exact number of floats the copy will produce. The API writes count floats into the caller-provided Float32Array and validates up front to avoid partial/overflowed writes.","triggerScenarios":"Calling CopyFloatData (or copyVerticesData reaching it) with a Float32Array allocated as totalVertices * size2, or allocated from a stale vertex count after the mesh's totalVertices changed, or forgetting to multiply by `size` (passing totalVertices only).","commonSituations":"Extracting positions (size=3) into an array sized for UVs (size=2); reusing a cached buffer after geometry was updated/re-tessellated; slicing Float32Array which can yield lengths not matching the new count.","solutions":["Allocate output as new Float32Array(totalVertices * size) using the same totalVertices and size passed to the copy.","Recompute the output buffer from the current vertexBuffer.getTotalVertices() and stride kind instead of caching.","For copyVerticesData, use vertexBuffer.getData()/copyToArray with a correctly sized target: totalVertices * (kind === 'uv' ? 2 : 3).","Trim oversized arrays with new Float32Array(buffer.buffer, 0, totalVertices * size) only when the source array is at least that long."],"exampleFix":"// before\nconst out = new Float32Array(mesh.getTotalVertices());\nCopyFloatData(input, stride, 3, type, totalVertices, normalized, offset, out); // out.length wrong\n\n// after\nconst size = 3;\nconst out = new Float32Array(mesh.getTotalVertices() * size);\nCopyFloatData(input, stride, size, type, totalVertices, normalized, offset, out);","handlingStrategy":"validation","validationCode":"const required = totalVertices * size;\nif (!(output instanceof Float32Array) || output.length !== required) {\n  output = new Float32Array(required);\n}\nCopyFloatData(input, byteStride, size, type, totalVertices, normalized, byteOffset, output);","typeGuard":"function isSizedFloat32Array(x, len) {\n  return x instanceof Float32Array && x.length === len;\n}","tryCatchPattern":"try {\n  CopyFloatData(input, stride, size, type, totalVertices, normalized, offset, out);\n} catch (e) {\n  if (e.message === 'Output length is not valid') {\n    out = new Float32Array(totalVertices * size);\n    CopyFloatData(input, stride, size, type, totalVertices, normalized, offset, out);\n  } else throw e;\n}","preventionTips":["Always size output arrays as totalVertices * size at the call site.","Recompute counts from the live geometry instead of cached values.","Name array variables with their kind and size (positions3F) to catch size mistakes.","Add a debug assert comparing output.length to totalVertices * size in dev builds."],"tags":["buffers","vertex-data","typedarray","babylonjs"],"backgroundTag":"output-length-mismatch","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}