stride3d/stride · error · NotImplementedException

Cannot create LiteralValue from the provided words

Error message

Cannot create LiteralValue from the provided words

What it means

Fallback branch of the LiteralValue words-based constructor: if T is not a primitive, not an Enum, and not a LiteralArray-named type, the constructor cannot know how to decode the raw int words into a T and throws NotImplementedException. Only types with an explicit encoding rule are accepted.

Solutions

  1. Decode the words into a supported type first (e.g. BitConverter/Unsafe reinterpret) and construct LiteralValue with that type.
  2. If T is an enum, ensure it actually derives from Enum (an interface won't match the `value is Enum` branch).
  3. For arrays use LiteralArray<T>.From; for strings ensure the words are null-terminated/word-padded UTF-8.
  4. Add a branch in the constructor if a new T encoding is genuinely required.

Example fix

// before
var lit = new LiteralValue<char>(words);
// after
var lit = new LiteralValue<ushort>(words); // then cast to char
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<Type> Allowed = new()
  { typeof(bool), typeof(byte), typeof(sbyte), typeof(short), typeof(ushort),
    typeof(Half), typeof(int), typeof(uint), typeof(float), typeof(long),
    typeof(ulong), typeof(double), typeof((int,int)), typeof(string) };
bool ok = Allowed.Contains(typeof(T)) || typeof(Enum).IsAssignableFrom(typeof(T));

Type guard

static bool IsDecodableLiteral<T>() => Allowed.Contains(typeof(T)) || typeof(Enum).IsAssignableFrom(typeof(T));

Try / catch

try { lit = new LiteralValue<T>(words); }
catch (NotImplementedException ex) when (ex.Message.Contains("Cannot create LiteralValue")) { /* decode words manually into a supported type */ }

Prevention

When it happens

Trigger: new LiteralValue<T>(words) where T is e.g. char, decimal, IntPtr, a custom struct, or an unsupported generic type — anything outside {bool, byte, sbyte, short, ushort, Half, int, uint, float, long, ulong, double, (int,int), string, Enum}.

Common situations: Deserializing SPIR-V OpConstant/OpLiteral operands with the wrong assumed type; generic parsing code parameterized over T; changing a constant's declared type in shader tooling without converting its words.

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/5d2342d761655bd2. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Spirv/Literals/LiteralValue.cs:102

            Span<char> sb = stackalloc char[words.Length * 4];
            for (int i = 0; i < words.Length; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    var c = (char)((words[i] >> (8 * j)) & 0xFF);
                    if (c == 0)
                        break;
                    sb[i * 4 + j] = c;
                }
            }
            Unsafe.As<T, string>(ref value) = SPool.GetOrAdd(sb.Contains('\0') ? sb[0..sb.IndexOf('\0')] : sb);
        }
        else if (value is Enum)
            Unsafe.As<T, int>(ref value) = words[0];
        else if (typeof(T).Name.Contains("LiteralArray"))
            throw new NotImplementedException("Use LiteralArray<T>.From instead");
        else
            throw new NotImplementedException("Cannot create LiteralValue from the provided words");

        Value = value;

        MemoryOwner = MemoryOwner<int>.Allocate(words.Length, AllocationMode.Clear);
        words.CopyTo(MemoryOwner.Span);
        UpdateMemory();
    }
    public LiteralValue(T value, bool dispose = false)
    {
        this.dispose = dispose;
        Value = value;
        MemoryOwner = MemoryOwner<int>.Empty;
        UpdateMemory();
    }

    void UpdateMemory()
    {
        int wordCount = Value switch

View on GitHub (pinned to 96fad776d2)