stride3d/stride · error · InvalidOperationException

Unexpected CubeMap, expecting all faces from DDS Header

Error message

Unexpected CubeMap, expecting all faces from DDS Header

What it means

Thrown by DecodeDDSHeader when a DDS file declares the CubeMap flag in its dwCubemap field but does not set all six per-face bits (AllFaces). The library requires all six cube faces to be present in the file and refuses to load a partial cube map rather than producing an incomplete texture.

Solutions

  1. Re-export the cube map so all six face flags are set in dwCubemap2 (0xFC00 | 0x200).
  2. Patch the DDS header cubemap face flags if the face data is known to be present (all 6 face-flag bits + the CubeMap bit).
  3. If only a 2D texture was intended, remove the CubeMap flag from the header so the file decodes as Texture2D.
  4. Wrap the load in a try-catch and treat the asset as invalid, prompting re-import.

Example fix

// before
var tex = Texture.Load(ddsStream);

// after
try { var tex = Texture.Load(ddsStream); }
catch (InvalidOperationException e) when (e.Message.Contains("expecting all faces"))
{
    log.Error("DDS cubemap is missing face flags; re-export with all 6 faces");
}
Defensive patterns

Strategy: validation

Validate before calling

// dwCubemap is at offset 28 of the DDS header (32 with magic)
uint cubemap = BitConverter.ToUInt32(ddsBytes, 4 + 28);
bool isCube = (cubemap & 0x200) != 0;
bool allFaces = (cubemap & 0xFC00) == 0xFC00;
if (isCube && !allFaces)
    throw new InvalidDataException("DDS cubemap missing one or more face flags");

Try / catch

try { texture = DdsLoader.Load(stream); }
catch (InvalidOperationException e) when (e.Message.Contains("expecting all faces"))
{
    texture = placeholderCubemap; // re-import asset
}

Prevention

When it happens

Trigger: Loading a .dds whose header sets DDCAPS2_CUBEMAP but omits one or more of DDCAPS2_CUBEMAP_POSITIVEX/NEGATIVEX/POSITIVEY/NEGATIVEY/POSITIVEZ/NEGATIVEZ flags, via any DDS decode entry point.

Common situations: DDS cube maps written by custom/buggy exporters that set the cubemap flag but forget the face flags; manually patched DDS headers; cube maps truncated during asset transfer.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

            }
            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
                        if ((header.CubemapFlags & DDS.CubemapFlags.AllFaces) != DDS.CubemapFlags.AllFaces)
                            throw new InvalidOperationException("Unexpected CubeMap, expecting all faces from DDS Header");

                        description.ArraySize = 6;
                        description.Dimension = TextureDimension.TextureCube;
                    }
                    else
                    {
                        description.Dimension = TextureDimension.Texture2D;
                    }

                    description.Width = header.Width;
                    description.Height = header.Height;
                    description.Depth = 1;
                    // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
                }

                description.Format = GetDXGIFormat(ref header.PixelFormat, flags, out convFlags);

                if (description.Format == PixelFormat.None)

View on GitHub (pinned to 96fad776d2)