{"record":{"id":"1f62fef98170f01c","repo":"stride3d/stride","slug":"cannot-pop-more-than-push","errorCode":null,"errorMessage":"Cannot pop more than push","messagePattern":"Cannot pop more than push","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Rendering/Rendering/RenderDrawContext.cs","lineNumber":98,"sourceCode":"                allocatedStates.Add(newState);\n            }\n            else\n            {\n                newState = allocatedStates[currentStateIndex];\n            }\n            newState.Capture(CommandList);\n\n            return new RenderTargetRestore(this);\n        }\n\n        /// <summary>\n        /// Restores render targets and viewport state.\n        /// </summary>\n        public void PopRenderTargets()\n        {\n            if (currentStateIndex < 0)\n            {\n                throw new InvalidOperationException(\"Cannot pop more than push\");\n            }\n\n            var oldState = allocatedStates[currentStateIndex--];\n            oldState.Restore(CommandList);\n        }\n\n        /// <summary>\n        /// Gets or creates a shared effect.\n        /// </summary>\n        /// <typeparam name=\"T\">Type of the shared effect (mush have a constructor taking a <see cref=\"Rendering.RenderContext\"/></typeparam>\n        /// <returns>A singleton instance of <typeparamref name=\"T\"/></returns>\n        public T GetSharedEffect<T>() where T : DrawEffect, new()\n        {\n            // TODO: Add a way to support custom constructor\n            lock (sharedEffects)\n            {\n                DrawEffect effect;\n                if (!sharedEffects.TryGetValue(typeof(T), out effect))","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Rendering/Rendering/RenderDrawContext.cs#L80-L116","documentation":"RenderDrawContext keeps a stack of render-target states: PushRenderTargets saves a state and PopRenderTargets restores one. Popping without a matching push (currentStateIndex < 0) leaves nothing to restore, so the engine throws InvalidOperationException to keep the push/pop pairs balanced.","triggerScenarios":"Calling PopRenderTargets more times than PushRenderTargets was called during a render frame, or calling Pop before any Push in the current frame context.","commonSituations":"Unbalanced error/early-exit paths in custom render features or renderers that push but skip the pop (or pop in a finally when push failed); calling pop from outside a RenderFeature's Execute scope.","solutions":["Ensure every PopRenderTargets call is paired with exactly one prior PushRenderTargets call in the same scope","Move push/pop into try/finally only around code that cannot throw before the push","Audit custom render features/pass ordering so a feature never pops a push owned by another feature"],"exampleFix":"// before\ncommandList.SetRenderTarget(...);\ncontext.PopRenderTargets(); // never pushed\n// after\ncontext.PushRenderTargets();\ncommandList.SetRenderTarget(...);\ncontext.PopRenderTargets(); // balanced pair","handlingStrategy":"validation","validationCode":"if (context.currentStateIndex < 0)\n    throw new InvalidOperationException(\"PopRenderTargets called without matching PushRenderTargets\");","typeGuard":null,"tryCatchPattern":"try { context.PopRenderTargets(); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Cannot pop more than push\") {\n    logger.Error(\"Unbalanced Push/PopRenderTargets in render feature\");\n}","preventionTips":["Always pair Push/Pop in the same method scope","Use try/finally only around code after a successful Push","Ensure each RenderFeature owns its own push/pop and doesn't pop another's state"],"tags":["rendering","render-pipeline","stack-balance"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}