stride3d/stride · error · NotImplementedException
Use LiteralArray .From instead
Error message
Use LiteralArray<T>.From instead
What it means
When building a LiteralValue<T> from raw words, the constructor detects T whose type name contains "LiteralArray" and refuses: arrays must be constructed through the dedicated LiteralArray<T>.From factory, which packs N words per element correctly. Passing raw words to LiteralValue would misinterpret the element count.
Solutions
- Replace the constructor call with LiteralArray<T>.From(words) (or the appropriate overload).
- If T is generic, branch: if typeof(T).Name.Contains("LiteralArray") use LiteralArray<T>.From, else use new LiteralValue<T>(words).
- Ensure the words slice corresponds to a single array constant, not mixed operands.
Example fix
// before var lit = new LiteralValue<LiteralArray<int>>(words); // after var arr = LiteralArray<int>.From(words);
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof(T).Name.Contains("LiteralArray"))
arr = LiteralArray<T>.From(words);
else
lit = new LiteralValue<T>(words); Type guard
static bool IsLiteralArrayType<T>() => typeof(T).Name.Contains("LiteralArray"); Try / catch
try { lit = new LiteralValue<T>(words); }
catch (NotImplementedException ex) when (ex.Message.Contains("LiteralArray<T>.From")) { arr = LiteralArray<T>.From(words); } Prevention
- Never construct array literals with the scalar LiteralValue constructor; always route through LiteralArray<T>.From.
- Centralize constant deserialization in one dispatcher that branches on typeof(T).
- Name-check types only at a single choke point rather than sprinkling construction calls.
When it happens
Trigger: Calling new LiteralValue<LiteralArray<int>>(words) (or any T named *LiteralArray*) via the words-based constructor instead of LiteralArray<T>.From.
Common situations: Manually deserializing SPIR-V constant instructions (OpConstantComposite arrays); copying construction code that worked for scalars and reusing it for array literals; generic SPIR-V parsing code that dispatches all constants through LiteralValue.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unsupported composite type
- Unsupported element type
- Exception of type 'System.InvalidOperationException' was…
- Type not supported in SPIR-V
- Type not supported in SPIR-V
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/6c26ec4d3362668a.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Spirv/Literals/LiteralValue.cs:100
else if (value is null && typeof(T) == typeof(string))
{
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()View on GitHub (pinned to 96fad776d2)