stride3d/stride · error · ArgumentException

Not enough size for destination buffer

Error message

Not enough size for destination buffer

What it means

Thrown by EncodeDDSHeader when the caller-provided destination buffer (maxsize) is smaller than the required size: the 4-byte magic header plus the DDS header plus, when needed, the DX10 extension header. It is an ArgumentException on the 'maxsize' parameter, thrown before any bytes are written.

Solutions

  1. Call EncodeDDSHeader once with pDestination = IntPtr.Zero to get the required size, allocate that, then call again with the real buffer.
  2. Allocate maxsize >= sizeof(uint) + sizeof(DDS.Header) + (needsDx10 ? sizeof(DDS.HeaderDXT10) : 0).
  3. Increase the buffer size and retry; catch ArgumentException on 'maxsize' to report the capacity shortfall.

Example fix

// before
var buf = new byte[128];
EncodeDDSHeader(desc, flags, buf);

// after
int required = EncodeDDSHeader(desc, flags, IntPtr.Zero, 0);
var buf = new byte[required];
EncodeDDSHeader(desc, flags, buf);
Defensive patterns

Strategy: try-catch

Validate before calling

int required = EncodeDDSHeader(desc, flags, IntPtr.Zero, 0); // probe pass
if (buffer.Length < required)
    throw new ArgumentException($"Buffer {buffer.Length} < required {required}", nameof(buffer));

Type guard

bool CanEncode(ReadOnlySpan<byte> buf, bool dx10) =>
    buf.Length >= sizeof(uint) + System.Runtime.CompilerServices.Unsafe.SizeOf<DDS.Header>()
    + (dx10 ? System.Runtime.CompilerServices.Unsafe.SizeOf<DDS.HeaderDXT10>() : 0);

Try / catch

try { EncodeDDSHeader(desc, flags, buffer); }
catch (ArgumentException e) when (e.ParamName == "maxsize")
{
    buffer = new byte[EncodeDDSHeader(desc, flags, IntPtr.Zero, 0)];
    EncodeDDSHeader(desc, flags, buffer);
}

Prevention

When it happens

Trigger: Calling EncodeDDSHeader (or higher-level Save-to-DDS APIs) with a preallocated buffer whose size is less than sizeof(uint) + sizeof(DDS.Header) (+ sizeof(DDS.HeaderDXT10) for DX10-extended files). Passing IntPtr.Zero skips writing and returns the required size instead — the throw only occurs for a non-null but too-small buffer.

Common situations: Reusing a buffer sized for a legacy DDS and then encoding a DX10-extended one (needs ~20 more bytes); hardcoding 128 as the header size and forgetting the 4-byte magic or the extension header; computing capacity from image data size only.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Foundation/Graphics/DDSHelper.cs:625

                        break;
                    case PixelFormat.R16_Float:
                        ddpf.Size = Unsafe.SizeOf<DDS.DDSPixelFormat>();
                        ddpf.Flags = DDS.PixelFormatFlags.FourCC;
                        ddpf.FourCC = 111; // D3DFMT_R16F
                        break;
                }
            }

            required = sizeof (int) + Unsafe.SizeOf<DDS.Header>();

            if (ddpf.Size == 0)
                required += Unsafe.SizeOf<DDS.HeaderDXT10>();

            if (pDestination == IntPtr.Zero)
                return;

            if (maxsize < required)
                throw new ArgumentException("Not enough size for destination buffer", "maxsize");

            *(uint*)(pDestination) = DDS.MagicHeader;

            var header = (DDS.Header*)((byte*)(pDestination) + sizeof (int));
            *header = default;
            header->Size = Unsafe.SizeOf<DDS.Header>();
            header->Flags = DDS.HeaderFlags.Texture;
            header->SurfaceFlags = DDS.SurfaceFlags.Texture;

            if (description.MipLevels > 0)
            {
                header->Flags |= DDS.HeaderFlags.Mipmap;
                header->MipMapCount = description.MipLevels;

                if (header->MipMapCount > 1)
                    header->SurfaceFlags |= DDS.SurfaceFlags.Mipmap;
            }

View on GitHub (pinned to 96fad776d2)