stride3d/stride · error · InvalidOperationException
Stream ' ' is expected as a vertex shader input and is…
Error message
Stream '{stream.Value.Name}'{readBy} is expected as a vertex shader input and is never written by any shader stage before being read. Without a semantic it cannot be sourced from a vertex buffer, so it has to be produced by a shader: write to streams.{stream.Value.Name} before reading it, or give it a semantic if it really is a vertex buffer input. What it means
After stream analysis, InterfaceProcessor.Process builds the vertex input layout from streams read by the vertex shader. A stream that is a vertex-shader input with an input-layout location but no semantic cannot come from a vertex buffer, so it must be produced by an earlier stage; since no stage writes it before being read, the processor throws with the stream name and reading method.
Solutions
- Write to the stream before reading it, e.g. assign streams.MyValue at the top of VSMain or in an earlier stage
- Add a semantic (e.g. [Semantic("POSITION")] / SV semantics) to the stream member so it is treated as a vertex-buffer input
- Check the composition for the missing mixin that was supposed to produce this stream, or fix the stream-name typo
Example fix
// before
struct StreamsOutput { [Location(0)] float4 Value; } // no semantic, never written
public override void Main() { float4 v = streams.Value; }
// after
struct StreamsOutput { [Location(0)][Semantic("POSITION")] float4 Value; }
public override void Main() { streams.Value = float4(0,0,0,1); float4 v = streams.Value; } Defensive patterns
Strategy: validation
Validate before calling
// Static review helper: every stream read in VSMain must be written or carry a semantic
foreach (var stream in vertexInputs)
{
if (!stream.IsWrittenByAnyStage && string.IsNullOrEmpty(stream.Semantic))
throw new InvalidOperationException($"Stream '{stream.Name}' has no semantic and no producer; add [Semantic(...)] or write to streams.{stream.Name} before reading.");
} Try / catch
try
{
mixer.MergeSDSL(shaderSource, options, log, out var bytecode, out _, out _, out _);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("expected as a vertex shader input"))
{
log.Error("Unsourced vertex stream: " + ex.Message);
} Prevention
- Assign every streams member before reading it in the vertex shader
- Give vertex-buffer-sourced streams explicit [Semantic] attributes
- After renaming streams, grep all stages for reads of the old name
- Verify every mixin that promises to produce a stream is actually composed in
When it happens
Trigger: MergeSDSL where the vertex entry point reads a streams.X member that (a) has no Semantic attached and (b) is never written by any earlier stage — e.g. a stream declared as input and read in VSMain without ever being assigned.
Common situations: Forgetting to assign a streams field in a previous stage or in the vertex shader itself; typo in the stream name so the write targets a different member; porting HLSL code where the semantic attribute was lost; a mixin expects another mixin to write the stream but is not composed in.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Can't cast from to (larger matrix)
- Can't cast from to
- Can't cast from to
- Can't figure array output size for tessellation shader
- Can't OpLoad with cbuffer
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/462d1a57bd1b3e52.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/InterfaceProcessor.cs:342
{
stream.Value.Output = true;
requirePosition = false;
}
}
}
entryPoints.Add(GenerateStreamWrapper(table, buffer, context, ExecutionModel.Vertex, entryPointVS, analysisResult, liveAnalysis, true));
// Process shader input attributes
foreach (var stream in streams)
{
// Note: built-ins won't have a inputLayoutLocation so they will be skipped
if (stream.Value.Input && stream.Value.InputLayoutLocation is { } inputLayoutLocation)
{
if (stream.Value.Semantic == null)
{
var readBy = stream.Value.ReadByMethod is { } m ? $" (read by '{m}')" : "";
throw new InvalidOperationException(
$"Stream '{stream.Value.Name}'{readBy} is expected as a vertex shader input and is never written by any shader stage before being read. " +
$"Without a semantic it cannot be sourced from a vertex buffer, so it has to be produced by a shader: " +
$"write to streams.{stream.Value.Name} before reading it, or give it a semantic if it really is a vertex buffer input.");
}
var semantic = SemanticAnalyzer.ParseSemantic(stream.Value.Semantic);
inputAttributes.Add(new ShaderInputAttributeDescription { Location = inputLayoutLocation, SemanticName = semantic.Name, SemanticIndex = semantic.Index });
}
}
}
}
// Emit all OpEntryPoints (deferred to allow fixups like adding dummy DS inputs for HS-internal outputs)
foreach (var ep in entryPoints)
context.Add(new OpEntryPoint(ep.Model, ep.Id, ep.Name, [.. ep.InterfaceVariables]));
// Entry points had their geometry stream parameter removed as their wrapper was
// generated; any other method carrying one has to lose it too.
RemoveGeometryStreamParameters(buffer, context);View on GitHub (pinned to 96fad776d2)