stride3d/stride · error · ArgumentException

Invalid Texture data length

Error message

Invalid Texture data length

What it means

Thrown when the TData[] passed to a Texture DataBox-building method does not exactly match the texture's computed data size: sizeof(TData) * Length must equal slicePitch * depth, where pitches come from Image.ComputePitch for the format. Ensures the fixed pointer covers the whole texture. Raised as ArgumentException.

Solutions

  1. Compute the required size with Image.ComputePitch(format, width, height, out rowPitch, out slicePitch, ...) and allocate textureData.Length = slicePitch * depth / sizeof(TData).
  2. Verify the generic type TData matches the format's bytes-per-pixel (or blocks for compressed formats).
  3. Log sizeof(TData) * Length vs slicePitch * depth to find the exact discrepancy.

Example fix

// before
var data = new byte[width * height * 4]; // ignores pitch padding
texture.SetData(commandList, data);
// after
Image.ComputePitch(format, width, height, out var rowPitch, out var slicePitch, out _, out _);
var data = new byte[slicePitch * depth];
texture.SetData(commandList, data);
Defensive patterns

Strategy: validation

Validate before calling

Image.ComputePitch(format, width, height, out _, out var slicePitch, out _, out _);
if (sizeof(TData) * textureData.Length != slicePitch * depth)
    throw new InvalidOperationException($"textureData size {sizeof(TData) * textureData.Length} != expected {slicePitch * depth}");

Try / catch

try { texture.SetData(cmd, data); }
catch (ArgumentException e) when (e.Message.Contains("Invalid Texture data length")) { log.Error("Texture buffer size mismatch", e); }

Prevention

When it happens

Trigger: Calling a Texture method that wraps raw data into a DataBox with a buffer sized to width*height*bytesPerPixel but ignoring row/slice pitch padding, or depth not accounted for.

Common situations: Compressed formats (BC1/BC3) where block-based pitch differs from naive width*4; padded rows on odd widths; 3D texture depth forgotten; buffer allocated for the wrong format.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/f9521f86624794ed. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/Texture.cs:1810

        /// <param name="width">The width in pixels of the Texture to calculate the <see cref="DataBox"/> for.</param>
        /// <param name="height">The height in pixels of the Texture to calculate the <see cref="DataBox"/> for.</param>
        /// <param name="depth">The depth in pixels of the Texture to calculate the <see cref="DataBox"/> for.</param>
        /// <param name="textureData">The data buffer to upload to the Texture.</param>
        /// <param name="fixedPointer">A pointer to the data buffer to upload to the Texture.</param>
        /// <returns>A <see cref="DataBox"/> structure describing the data and its memory layout.</returns>
        /// <exception cref="ArgumentException">
        ///   The length of <paramref name="textureData"/> and data type <typeparamref name="TData"/> are incorrect for
        ///   the specified size and pixel <paramref name="format"/>.
        /// </exception>
        private static unsafe DataBox GetDataBox<TData>(PixelFormat format, int width, int height, int depth, TData[] textureData, IntPtr fixedPointer) where TData : unmanaged
        {
            ArgumentNullException.ThrowIfNull(textureData);

            // Check that the textureData has the correct size for the Texture's data
            Image.ComputePitch(format, width, height, out var rowPitch, out var slicePitch, out _, out _);

            if (sizeof(TData) * textureData.Length != (slicePitch * depth))
                throw new ArgumentException("Invalid Texture data length", nameof(textureData));

            return new DataBox(fixedPointer, rowPitch, slicePitch);
        }

        /// <summary>
        ///   Swaps the Texture's internal data with another Texture.
        /// </summary>
        /// <param name="other">The other Texture.</param>
        internal void Swap([NotNull] Texture other)
        {
            if (ParentTexture is not null || other.ParentTexture is not null)
                throw new NotSupportedException("Cannot swap texture views; only root textures can be swapped.");

            (textureDescription, other.textureDescription) = (other.textureDescription, textureDescription);
            (textureViewDescription, other.textureViewDescription) = (other.textureViewDescription, textureViewDescription);
            (mipmapDescriptions, other.mipmapDescriptions) = (other.mipmapDescriptions, mipmapDescriptions);
            (fullQualitySize, other.fullQualitySize) = (other.fullQualitySize, fullQualitySize);

View on GitHub (pinned to 96fad776d2)