stride3d/stride · error · NotSupportedException

AlphaLoadMode.{alphaLoadMode} not supported for the Stride i

Error message

AlphaLoadMode.{alphaLoadMode} not supported for the Stride image format (no premultiplied-state metadata).

What it means

LoadFromMemory parsing a Stride-native image (.sdtex) refuses any AlphaLoadMode other than Preserve. The Stride image container has no metadata recording whether pixel data is already premultiplied, so the library cannot correctly perform premultiply/unpremultiply conversions and throws NotSupportedException instead of silently producing wrong alpha. Thrown as NotSupportedException from LoadFromMemory in ImageHelper.cs when alphaLoadMode != AlphaLoadMode.Preserve.

Solutions

  1. Pass AlphaLoadMode.Preserve when loading Stride-format images.
  2. Convert the asset to a format with premultiplied-state metadata (e.g. PNG or DDS) if alpha conversion is required.
  3. Branch on format first (read the magic code yourself) and only pass non-Preserve modes to formats that support it.

Example fix

// before
var image = ImageHelper.LoadFromMemory(stream, makeACopy: true, alphaLoadMode: AlphaLoadMode.Premultiply);
// after
var image = ImageHelper.LoadFromMemory(stream, makeACopy: true, alphaLoadMode: AlphaLoadMode.Preserve);
Defensive patterns

Strategy: validation

Validate before calling

if (alphaLoadMode != AlphaLoadMode.Preserve)
    throw new ArgumentException($"{alphaLoadMode} requires a format with premultiplied-state metadata; use Preserve for Stride images.");

Try / catch

try { image = ImageHelper.LoadFromMemory(stream, makeACopy, alphaLoadMode); }
catch (NotSupportedException) { image = ImageHelper.LoadFromMemory(stream, makeACopy, AlphaLoadMode.Preserve); }

Prevention

When it happens

Trigger: Calling ImageHelper.LoadFromMemory(stream, makeACopy, alphaLoadMode) with a stream whose magic code matches the Stride image format, while passing AlphaLoadMode.Premultiply or AlphaLoadMode.Unpremultiply. Only AlphaLoadMode.Preserve is valid for this container format.

Common situations: Sharing one image-loading code path across file formats where non-Stride loaders (e.g. PNG via StandardImageHelper) do honor alpha load modes; refactoring code that used to load PNGs to load Stride-native images; explicitly requesting premultiplied data for rendering pipelines that require it.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Foundation/Graphics/ImageHelper.cs:32

    public class ImageHelper
    {
        internal static DataSerializer<ImageDescription> ImageDescriptionSerializer = SerializerSelector.Default.GetSerializer<ImageDescription>();
        internal static readonly FourCC MagicCode = "TKTX";

        public static unsafe Image LoadFromMemory(IntPtr pSource, int size, bool makeACopy, GCHandle? handle, AlphaLoadMode alphaLoadMode)
        {
            Debug.Assert(size >= 0);
            var ums = new UnmanagedMemoryStream((byte*)pSource, size, capacity: size, access: FileAccess.Read);
            var stream = new BinarySerializationReader(ums);

            // Read and check magic code
            var magicCode = stream.ReadUInt32();
            if (magicCode != MagicCode)
                return null;

            // Stride's own format doesn't carry a premul-state flag; we can't honor conversion requests safely.
            if (alphaLoadMode != AlphaLoadMode.Preserve)
                throw new NotSupportedException($"AlphaLoadMode.{alphaLoadMode} not supported for the Stride image format (no premultiplied-state metadata).");

            // Read header
            var imageDescription = new ImageDescription();
            ImageDescriptionSerializer.Serialize(ref imageDescription, ArchiveMode.Deserialize, stream);

            if (makeACopy)
            {
                var buffer = MemoryUtilities.Allocate(size);
                MemoryUtilities.CopyWithAlignmentFallback((void*)buffer, source: (void*)pSource, (uint)size);
                pSource = buffer;
                makeACopy = false;
            }

            var image = new Image(imageDescription, pSource, 0, handle, !makeACopy);

            var totalSizeInBytes = stream.ReadInt32();
            if (totalSizeInBytes != image.TotalSizeInBytes)
                throw new InvalidOperationException("Image size is different than expected.");

View on GitHub (pinned to 96fad776d2)