{"record":{"id":"4aa504720e948b4b","repo":"theonedev/onedev","slug":"cannot-modify-component-hierarchy-after-render-pha","errorCode":null,"errorMessage":"Cannot modify component hierarchy after render phase has started (page version cant change then anymore)","messagePattern":"Cannot modify component hierarchy after render phase has started \\(page version cant change then anymore\\)","errorType":"exception","errorClass":"WicketRuntimeException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/org/apache/wicket/Component.java","lineNumber":3680,"sourceCode":"\n\t\t\t\tfindMarkupStream().throwMarkupException(msg);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether the hierarchy may be changed at all, and throws an exception if this is not\n\t * the case.\n\t * \n\t * @param component\n\t *            the component which is about to be added or removed\n\t */\n\tprotected void checkHierarchyChange(final Component component)\n\t{\n\t\t// Throw exception if modification is attempted during rendering\n\t\tif (getFlag(FLAG_RENDERING) && !component.isAuto())\n\t\t{\n\t\t\tthrow new WicketRuntimeException(\n\t\t\t\t\"Cannot modify component hierarchy after render phase has started (page version cant change then anymore)\");\n\t\t}\n\t}\n\n\t/**\n\t * Detaches the model for this component if it is detachable.\n\t */\n\tprotected void detachModel()\n\t{\n\t\tIModel<?> model = getModelImpl();\n\t\tif (model != null)\n\t\t{\n\t\t\tmodel.detach();\n\t\t}\n\t\t// also detach the wrapped model of a component assigned wrap (not\n\t\t// inherited)\n\t\tif (model instanceof IWrapModel && !getFlag(FLAG_INHERITABLE_MODEL))\n\t\t{","sourceCodeStart":3662,"sourceCodeEnd":3698,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/org/apache/wicket/Component.java#L3662-L3698","documentation":"checkHierarchyChange() throws WicketRuntimeException when code tries to add/remove/replace components while the page is being rendered (FLAG_RENDERING is set) and the component is not auto-added. Once rendering started, the page version is committed and structural changes would corrupt the rendered output, so Wicket forbids them.","triggerScenarios":"Calling add(), remove(), replace() or similar hierarchy mutations from code that runs during rendering: onBeforeRender of a sibling, during renderHead, inside render of another component, or from behaviors rendering late.","commonSituations":"Dynamically adding components in onBeforeRender after render phase began; updating a ListView during rendering; adding components from an AJAX request handler that runs mid-render; page-relative lazy initialization done too late.","solutions":["Move hierarchy changes earlier in the lifecycle: constructor, onInitialize, or onBeforeRender before the render flag is set.","If the change must happen during render, mark the component auto-added (component.setAuto(true)) or pre-build children in onInitialize.","Use AJAX mechanisms (target.add / add children before rendering) instead of mutating the hierarchy mid-render.","Check for accidental render-time mutation, e.g. calling add() inside renderHead or onRender."],"exampleFix":"// before\n@Override\nprotected void onBeforeRender() {\n    add(new Label(\"extra\")); // may run after render started\n    super.onBeforeRender();\n}\n// after\n@Override\nprotected void onInitialize() {\n    super.onInitialize();\n    add(new Label(\"extra\")); // safe: before render phase\n}","handlingStrategy":"validation","validationCode":"if (component.getPage() != null && component.findParent(Page.class) != null && component.isPreparedForRender()) {\n    throw new IllegalStateException(\"too late to modify hierarchy\");\n}","typeGuard":null,"tryCatchPattern":"try { parent.add(child); } catch (WicketRuntimeException e) { target.add(parent); // or restructure to build children in onInitialize }","preventionTips":["Create and add child components in constructors or onInitialize, never in onRender/renderHead.","Use ListView/RepeatingView for dynamic children instead of add() at render time.","Enable Component.checksAreOn during development to catch lifecycle misuse early."],"tags":["wicket","lifecycle","render-phase","hierarchy"],"backgroundTag":"invalid-state-transition","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}