stride3d/stride · error · InvalidOperationException

Unexpected dimension

Error message

Unexpected dimension [{0}] from DDS HeaderDX10

What it means

Thrown by DecodeDDSHeader when a DDS file uses the DX10 extension header (HeaderDXT10) whose ResourceDimension field contains a value the parser does not recognize as Texture2D, Texture3D, or an accepted dimension. The library validates the enum strictly rather than guessing, because a wrong dimension would misinterpret the whole texture layout.

Solutions

  1. Re-export the DDS with a conformant tool (texconv, Compressonator, or the engine's exporter) so resourceDimension is a valid D3D10_RESOURCE_DIMENSION value.
  2. Inspect bytes 32-35 of the DX10 extension header (offset 128+20 in the file) and confirm resourceDimension is 2 (TEXTURE2D) or 3 (TEXTURE3D).
  3. If the texture is a plain 2D texture, re-save it without the DX10 extension header (legacy DDS header) so this code path is skipped.
  4. Catch InvalidOperationException around the decode call and reject/fall back for the offending asset.

Example fix

// before
classifyDds(file);

// after
try { classifyDds(file); }
catch (InvalidOperationException e) when (e.Message.Contains("DDS HeaderDX10"))
{
    log.Error($"{file}: invalid DX10 resourceDimension, re-export the texture");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// resourceDimension is the first uint of the DX10 header (offset 128+20)
uint dim = BitConverter.ToUInt32(ddsBytes, 128 + 20);
bool hasDx10 = BitConverter.ToUInt32(ddsBytes, 128 - 4 + 16 * 7) != 0 || ddsBytes.Length > 128 + 20;
if (hasDx10 && dim != 2 && dim != 3)
    throw new InvalidDataException($"DDS DX10 resourceDimension {dim} is invalid");

Type guard

bool IsValidDx10Dimension(uint dim) => dim is 2 or 3; // TEXTURE2D or TEXTURE3D

Try / catch

try { texture = DdsLoader.Load(stream); }
catch (InvalidOperationException e) when (e.Message.Contains("from DDS HeaderDX10"))
{
    ReportInvalidAsset(assetPath, e.Message);
}

Prevention

When it happens

Trigger: Calling DirectXTex/Stride DDS loading APIs (e.g. DDSHelper.LoadDDSFromStream / Image.Load on a .dds) on a file whose DDSD_HEADER10 resourceDimension field is corrupted, zero, or written by a non-conformant tool with an out-of-range value (not 2/3/4 for 2D/3D/Cube-compatible dimensions).

Common situations: Hand-edited or truncated DDS files; DDS files exported by third-party tools that misfill the DX10 extension header; files renamed to .dds that are actually other formats; older texture pipeline tools producing nonstandard DX10 headers.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

                        description.Height = header.Height;
                        description.Depth = 1;
                        break;

                    case DDS.ResourceDimension.Texture3D:
                        if ((header.Flags & DDS.HeaderFlags.Volume) == 0)
                            throw new InvalidOperationException("Texture3D missing HeaderFlags.Volume from DDS HeaderDX10");

                        if (description.ArraySize > 1)
                            throw new InvalidOperationException("Unexpected ArraySize > 1 for Texture3D from DDS HeaderDX10");

                        description.Width = header.Width;
                        description.Height = header.Height;
                        description.Depth = header.Depth;
                        description.Dimension = TextureDimension.Texture3D;
                        break;

                    default:
                        throw new InvalidOperationException(string.Format("Unexpected dimension [{0}] from DDS HeaderDX10", headerDX10.ResourceDimension));
                }
            }
            else
            {
                description.ArraySize = 1;

                if ((header.Flags & DDS.HeaderFlags.Volume) != 0)
                {
                    description.Width = header.Width;
                    description.Height = header.Height;
                    description.Depth = header.Depth;
                    description.Dimension = TextureDimension.Texture3D;
                }
                else
                {
                    if ((header.CubemapFlags & DDS.CubemapFlags.CubeMap) != 0)
                    {
                        // We require all six faces to be defined

View on GitHub (pinned to 96fad776d2)