{"record":{"id":"d1504e2b604ff3d1","repo":"octobercms/october","slug":"cannot-end-component-no-active-component","errorCode":null,"errorMessage":"Cannot end component: no active component.","messagePattern":"Cannot end component: no active component\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"modules/system/classes/ViewComponent.php","lineNumber":101,"sourceCode":"        // Close previous slot\n        if ($instance->currentSlot !== null) {\n            $instance->slots[$instance->currentSlot] = ob_get_clean();\n        }\n\n        // Start new slot\n        ob_start();\n        $instance->currentSlot = $name;\n    }\n\n    /**\n     * endComponent captures the final slot and renders the component\n     */\n    public static function endComponent(): void\n    {\n        $instance = array_pop(static::$stack);\n\n        if ($instance === null) {\n            throw new \\RuntimeException(\"Cannot end component: no active component.\");\n        }\n\n        // Capture final slot\n        if ($instance->currentSlot !== null) {\n            $instance->slots[$instance->currentSlot] = ob_get_clean();\n        }\n\n        echo $instance->render();\n    }\n    /**\n     * __call supports fluent API for setting props\n     */\n    public function __call(string $method, array $args): static\n    {\n        $this->props[$method] = $args[0] ?? true;\n        return $this;\n    }\n","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/classes/ViewComponent.php#L83-L119","documentation":"ViewComponent::endComponent() (exposed as UiFactory::end()) pops the last component off the static stack, captures its final slot, and echoes the rendered result. When array_pop() returns null the stack was already empty, and it throws a RuntimeException: more end() calls than component starts in the current render. Typical markup imbalance — an extra @end / UiFactory::end(), or an end() outside a condition whose matching ->slot() open never ran.","triggerScenarios":"An extra UiFactory::end() in a template; an end() in an else-branch while the ->slot() open was in the if-branch; duplicated footer/partial that also contains an end(); calling endComponent() directly without ever calling ->slot().","commonSituations":"Copy-pasted partials that each carry their own end(); refactoring that leaves orphan close tags; conditionals that pair opens and closes asymmetrically.","solutions":["Count `->slot()` opens versus UiFactory::end() closes in the failing template and its partials — they must pair 1:1 on every code path","Check conditionals/loops: each branch that renders an end() must also have rendered the open in the same branch","Remove stray end() calls duplicated by includes/partials","Prefer the inline `<?= UiFactory::button(...) ?>` form for simple components to avoid manual pairing entirely"],"exampleFix":"// before — extra end() with no matching open\n<?php UiFactory::card(title: 'A')->slot() ?>\n    <p>One</p>\n<?php UiFactory::end() ?>\n<?php UiFactory::end() ?>  <!-- RuntimeException: no active component -->\n// after — one open, one close\n<?php UiFactory::card(title: 'A')->slot() ?>\n    <p>One</p>\n<?php UiFactory::end() ?>","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function hasOpenViewComponent(): bool\n{\n    $prop = new ReflectionProperty(\\System\\Classes\\ViewComponent::class, 'stack');\n    return !empty($prop->getValue());\n}\n\nif (hasOpenViewComponent()) {\n    \\System\\Classes\\ViewComponent::endComponent();\n} else {\n    throw new LogicException('Unbalanced UiFactory template: extra end()');\n}","tryCatchPattern":null,"preventionTips":["Keep component open/close blocks contiguous — no interleaved partials that own the other half","Wrap whole components in single if/else branches, never split across them","Code-review copy-pasted partials for duplicated end() calls"],"tags":["octobercms","view","component","slot","output-buffer"],"backgroundTag":"unbalanced-view-nesting","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}