stride3d/stride · error · NotImplementedException
Unsupported format when converting vertex element
Error message
Unsupported format when converting vertex element ({format}) What it means
This is the interleaved-copy path of VertexBufferHelper: it dispatches on the element's PixelFormat to choose a typed InterleavedCopy<T,...> instantiation. Only R32G32B32A32_Float, R16G16_Float, R16G16B16A16_Float, R16G16B16A16_UInt, R8G8B8A8_UInt and R8G8B8A8_UNorm are handled; any other format falls through to default and throws NotImplementedException. The library refuses to guess how to convert an unknown pixel layout.
Solutions
- Change the vertex declaration to use a supported PixelFormat for that element
- Pre-convert the vertex data into one of the six supported formats before conversion
- Add a case to the format switch that calls InterleavedCopy with an appropriate unmanaged source type
- Log elementData format values when the error occurs to know exactly which one to add or convert
Example fix
// before
new VertexElement("POSITION", 0, PixelFormat.R32G32B32_Float, 0) // throws
// after
new VertexElement("POSITION", 0, PixelFormat.R32G32B32A32_Float, 0) // supported Defensive patterns
Strategy: validation
Validate before calling
if (!supportedFormats.Contains(elementFormat))
throw new InvalidOperationException($"Interleaved conversion unsupported for {elementFormat}"); Try / catch
try { ConvertInterleaved(param); }
catch (NotImplementedException ex) { logger.Error(ex, "Unsupported interleaved vertex format"); throw; } Prevention
- Normalize vertex formats to supported ones during import
- Keep custom declarations aligned with Stride's supported format list
- Log all element formats of assets during pipeline runs
When it happens
Trigger: Calling the interleaved vertex conversion API (Convert with interleaved parameters) where the source vertex element's format is not one of the six supported PixelFormats, e.g. R32G32B32_Float or R8G8_UNorm.
Common situations: Mesh assets exported with compact or snorm formats from other tools; changing vertex compression settings in the pipeline; using a custom vertex declaration whose format differs from Stride's defaults.
Related errors
- Unsupported format when converting vertex element
- Unsupported format when converting vertex element
- Invalid Z slice index
- MipLevels must be <=
- Width/Height/Depth must be power of 2
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/edb95e3352bac824.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/VertexBufferHelper.cs:176
IConverter<Half2, TOutput>,
IConverter<Half4, TOutput>,
IConverter<UShort4, TOutput>,
IConverter<Byte4, TOutput>,
IConverter<Color, TOutput>,
ISemantic
where TOutput : unmanaged
{
switch (format)
{
case PixelFormat.R32G32_Float: InterleavedCopy<TSemantic, Vector2, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R32G32B32_Float: InterleavedCopy<TSemantic, Vector3, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R32G32B32A32_Float: InterleavedCopy<TSemantic, Vector4, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R16G16_Float: InterleavedCopy<TSemantic, Half2, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R16G16B16A16_Float: InterleavedCopy<TSemantic, Half4, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R16G16B16A16_UInt: InterleavedCopy<TSemantic, UShort4, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R8G8B8A8_UInt: InterleavedCopy<TSemantic, Byte4, TOutput>(param, srcElemOffset, destElemOffset); break;
case PixelFormat.R8G8B8A8_UNorm: InterleavedCopy<TSemantic, Color, TOutput>(param, srcElemOffset, destElemOffset); break;
default: throw new NotImplementedException($"Unsupported format when converting vertex element ({format})");
}
}
static void InterleavedCopy<TConverter, TSourceSemVal, TDestSemVal>(InterleavedParameters param, int srcElemOffset, int destElemOffset)
where TConverter : IConverter<TSourceSemVal, TDestSemVal>
where TSourceSemVal : unmanaged
where TDestSemVal : unmanaged
{
fixed (byte* srcStart = param.Source)
fixed (byte* destStart = param.Destination)
{
for (byte*
src = srcStart + srcElemOffset,
dest = destStart + destElemOffset,
endSrc = src + param.VertexCount * param.SourceStride;
src < endSrc;
View on GitHub (pinned to 96fad776d2)