stride3d/stride · error · InvalidOperationException
Expecting texture output on slot
Error message
Expecting texture output on slot [{0}] What it means
GetSafeOutput fetches the output render target via GetOutput and throws InvalidOperationException when the result is null, i.e. no output was ever bound (SetOutput never called, or slot beyond bound views). It guarantees a non-null texture for the caller.
Solutions
- Call SetOutput with the destination render target before drawing/reading
- Ensure the effect's Draw executed before consuming outputs
- Verify index is within the number of outputs passed to SetOutput(params ...)
Example fix
// before var outTex = effect.GetSafeOutput(0); // no output bound // after effect.SetOutput(myRenderTarget); // ... draw ... var outTex = effect.GetSafeOutput(0);
Defensive patterns
Strategy: validation
Validate before calling
if (!outputBound) throw new InvalidOperationException("Call SetOutput before reading effect output"); Type guard
bool HasOutput(ImageEffect e, int i) => i == 0 ? e.GetOutput(0) != null : e.GetOutput(i) != null;
Try / catch
try { var tex = effect.GetSafeOutput(index); } catch (InvalidOperationException) { /* bind output before draw */ } Prevention
- Always call SetOutput before Draw and before reading results
- Preserve output binding across render-target resizes
- Verify effect execution order in the render pipeline
When it happens
Trigger: Calling effect.GetSafeOutput(index) before any SetOutput/SetOutput(params) call, or with an index exceeding the number of bound outputs (outputRenderTargetViews[i] is null or array access issues).
Common situations: Reading an effect's result before Draw ran; a code path skipped SetOutput during render-target resize; mixing single-output (outputRenderTargetView) and multi-output configurations.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Expecting texture input on slot
- Begin must be called before functionName
- End must be called before functionName
- Expecting less than textures in input
- This method can only be called during step
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/6126aced27e1e584.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Rendering/Rendering/Images/ImageEffect.cs:413
{
throw new ArgumentOutOfRangeException("index", string.Format("Invald texture outputindex [{0}] cannot be negative for effect [{1}]", index, Name));
}
return outputRenderTargetView ?? (outputRenderTargetViews != null ? outputRenderTargetViews[index] : null);
}
/// <summary>
/// Gets an non-null output render target for the specified index.
/// </summary>
/// <param name="index">The index.</param>
/// <returns>RenderTarget.</returns>
/// <exception cref="System.InvalidOperationException"></exception>
protected Texture GetSafeOutput(int index)
{
var output = GetOutput(index);
if (output == null)
{
throw new InvalidOperationException(string.Format("Expecting texture output on slot [{0}]", index));
}
return output;
}
/// <summary>
/// Gets a render target with the specified description, scoped for the duration of the <see cref="RendererBase.DrawCore"/>.
/// </summary>
/// <returns>A new instance of texture.</returns>
protected Texture NewScopedRenderTarget2D(TextureDescription description)
{
// TODO: Check if we should introduce an enum for the kind of scope (per DrawCore, per Frame...etc.)
CheckIsInDrawCore();
return PushScopedResource(Context.Allocator.GetTemporaryTexture2D(description));
}
/// <summary>
/// Gets a render target output for the specified description with a single mipmap, scoped for the duration of the <see cref="RendererBase.DrawCore"/>.View on GitHub (pinned to 96fad776d2)