{"record":{"id":"068163659f472e50","repo":"stride3d/stride","slug":"type-vertex-can-t-be-a-byte","errorCode":null,"errorMessage":"Type vertex can't be a byte","messagePattern":"Type vertex can't be a byte","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/VertexHelper.cs","lineNumber":209,"sourceCode":"\n            var allVertexElements = new List<VertexElement>(vertexDeclaration.VertexElements);\n            allVertexElements.AddRange(newVertexElements);\n\n            return new VertexTransformResult(new VertexDeclaration(allVertexElements.ToArray()), newVertexBuffer);\n        }\n\n        /// <summary>\n        /// Generates the tangent binormal for an existing vertex buffer.\n        /// </summary>\n        /// <param name=\"vertexDeclaration\">The vertex declaration.</param>\n        /// <param name=\"vertexBufferData\">The vertex buffer data.</param>\n        /// <param name=\"indexBuffer\">The index buffer.</param>\n        /// <returns>A new vertex buffer with its new layout.</returns>\n        public static unsafe VertexTransformResult GenerateTangentBinormal<T>(VertexDeclaration vertexDeclaration, T[] vertexBufferData, int[] indexBuffer) where T : unmanaged\n        {\n            if (vertexDeclaration == null) throw new ArgumentNullException(\"vertexDeclaration\");\n            if (vertexBufferData == null) throw new ArgumentNullException(\"vertexBufferData\");\n            if (typeof(T) == typeof(byte)) throw new ArgumentOutOfRangeException(\"T\", \"Type vertex can't be a byte\");\n\n            var vertexStride = Unsafe.SizeOf<T>();\n            fixed (void* vertexBufferPtr = vertexBufferData)\n            fixed (void* indexBufferPtr = indexBuffer)\n            {\n                return GenerateTangentBinormal(vertexDeclaration, (nint)vertexBufferPtr, vertexBufferData.Length, 0, vertexStride, (nint)indexBufferPtr, true, indexBuffer?.Length ?? 0);\n            }\n        }\n\n        /// <summary>\n        /// Generate Tangent BiNormal from an existing vertex/index buffer.\n        /// </summary>\n        /// <param name=\"vertexDeclaration\">The vertex declaration of the vertex buffer passed by parameters.</param>\n        /// <param name=\"vertexBufferData\">The vertex buffer.</param>\n        /// <param name=\"vertexCount\">The vertex count.</param>\n        /// <param name=\"vertexOffset\">The vertex offset.</param>\n        /// <param name=\"vertexStride\">The vertex stride. If 0, It takes the stride from the vertex declaration</param>\n        /// <param name=\"indexData\">The index data.</param>","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/VertexHelper.cs#L191-L227","documentation":"The generic overload GenerateTangentBinormal<T> only supports unmanaged vertex structs with a meaningful layout; T == byte is rejected with ArgumentOutOfRangeException because byte gives stride 1 and no way to interpret vertex semantics.","triggerScenarios":"Calling VertexHelper.GenerateTangentBinormal<byte>(declaration, rawBytes, indexBuffer) — typically when holding the vertex data as a raw byte array copied from a buffer.","commonSituations":"Reading vertex data back from a GPU buffer into byte[] then passing it straight into the generic API; serializing code paths that treat vertex data as opaque bytes.","solutions":["Define or use a proper vertex struct (e.g. PositionNormalTexture) and cast/copy the bytes into T[] before calling.","Use the non-generic overload taking IntPtr, vertexCount, and vertexStride instead of the generic byte invocation.","Use VertexHelper.Convert / BytesToTypedArray-style conversion utilities to reinterpret the data."],"exampleFix":"// before\nbyte[] raw = mesh.GetVertexBytes();\nvar result = VertexHelper.GenerateTangentBinormal(declaration, raw, indexBuffer);\n\n// after\nvar verts = new PositionNormalTexture[raw.Length / declaration.VertexStride];\nBuffer.BlockCopy(raw, 0, verts, 0, raw.Length);\nvar result = VertexHelper.GenerateTangentBinormal(declaration, verts, indexBuffer);","handlingStrategy":"type-guard","validationCode":"if (typeof(T) == typeof(byte))\n    throw new InvalidOperationException(\"Convert raw bytes to a vertex struct before calling GenerateTangentBinormal\");","typeGuard":"bool IsSupportedVertexType<T>() where T : unmanaged => typeof(T) != typeof(byte);","tryCatchPattern":"try { var result = VertexHelper.GenerateTangentBinormal(decl, data, indices); }\ncatch (ArgumentOutOfRangeException ex) { log.Error(\"Unsupported vertex element type; use a real vertex struct\", ex); }","preventionTips":["Keep vertex data typed as dedicated structs, not byte[]","Convert raw bytes with Buffer.BlockCopy into T[] before transforms","Use the IntPtr overload for opaque native data instead of T=byte"],"tags":["graphics","type-mismatch","generics"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}