stride3d/stride · error · InvalidOperationException
Bound render targets
Error message
Bound render targets ({RenderTargetCount} color, depth: {depthStencilBuffer != null}) do not match the active pipeline's output ({output.RenderTargetCount} color, depth: {output.DepthStencilFormat != PixelFormat.None}). The render targets bound on the command list must match the pipeline's Output description. What it means
In debug mode, Stride validates that the render targets bound on the command list match the active pipeline's Output description (number of color targets and presence of a depth-stencil). Mismatches are undefined behavior on strict Vulkan drivers, so Stride fails loudly with a detailed message.
Solutions
- Recreate the pipeline state with an Output description matching the currently bound render targets
- Adjust SetRenderTargets to bind exactly the number of color targets and depth buffer the pipeline's Output declares
- Verify EffectPass/PipelineState selection matches the current framebuffer layout
Example fix
// before var pipeline = PipelineState.New(..., new RenderOutputDescription(2, PixelFormat.R8G8B8A8_UNorm)); SetRenderTargetCount(1) // mismatch // after var pipeline = PipelineState.New(..., new RenderOutputDescription(1, PixelFormat.R8G8B8A8_UNorm, PixelFormat.D32_Float));
Defensive patterns
Strategy: validation
Validate before calling
var out0 = pipelineState.Description.Output;
if (cmdList.RenderTargetCount != out0.RenderTargetCount) throw new InvalidOperationException("Bind render targets matching pipeline Output"); Try / catch
try { cmdList.Draw(...); } catch (InvalidOperationException ex) when (ex.Message.Contains("Bound render targets")) { /* rebind correct targets or select matching pipeline */ } Prevention
- Derive PipelineState Output from the exact framebuffer/rendertarget layout in use
- Use EffectPass/PipelineState caches keyed by RenderOutputDescription
- Enable debug mode in development to catch mismatches early
When it happens
Trigger: Setting a pipeline compiled for N color targets (with/without depth) while SetRenderTargets bound a different count or depth buffer, then executing a draw inside command list execution on Vulkan.
Common situations: Reusing a pipeline (effect/pass) with a framebuffer configured differently; binding depth buffer when the pipeline output has DepthStencilFormat None or vice versa; MRT pipelines applied to single-target framebuffers.
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
- (bytecode [ ])
- The specified semantic name is too long. Usually it should…
- Invalid Shader stage specified in the Effect bytecode.
- Invalid PrimitiveType in PipelineStateDescription.
- Cannot specify the format for more than 8 Render Targets.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/5b0c179dad541479.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs:1682
// attachments and the depth layout stay the same
if (activeRendering && !renderingDirty && activeDepthReadOnly == depthReadOnly)
return;
// End old render pass instance
CleanupRenderPass();
var renderTarget = RenderTargetCount > 0 ? renderTargets[0] : depthStencilBuffer;
if (renderTarget == null)
return;
// An attachment mismatch with the pipeline's declared formats is undefined behavior that
// loses the device on strict drivers; fail loud in debug (only, to not break drivers that
// tolerate it) instead.
if (GraphicsDevice.IsDebugMode)
{
var output = activePipeline.Description.Output;
if (RenderTargetCount != output.RenderTargetCount || (depthStencilBuffer != null) != (output.DepthStencilFormat != PixelFormat.None))
throw new InvalidOperationException(
$"Bound render targets ({RenderTargetCount} color, depth: {depthStencilBuffer != null}) do not match the active pipeline's output " +
$"({output.RenderTargetCount} color, depth: {output.DepthStencilFormat != PixelFormat.None}). The render targets bound on the command list must match the pipeline's Output description.");
}
// Clear attachments if needed
for (int index = 0; index < RenderTargetCount; index++)
{
if (!renderTarget.IsInitialized)
{
Clear(renderTargets[index], Color.Transparent);
}
}
if (depthStencilBuffer != null && !depthStencilBuffer.IsInitialized)
{
Clear(depthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
}
View on GitHub (pinned to 96fad776d2)