{"record":{"id":"3bc813ed2e193c7a","repo":"theonedev/onedev","slug":"model-for","errorCode":null,"errorMessage":"Model for ","messagePattern":"Model for ","errorType":"exception","errorClass":"WicketRuntimeException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/org/apache/wicket/Component.java","lineNumber":3794,"sourceCode":"\t\treturn (requestFlags & flag) != 0;\n\t}\n\n\t/**\n\t * Finds the innermost IModel object for an IModel that might contain nested IModel(s).\n\t * \n\t * @param model\n\t *            The model\n\t * @return The innermost (most nested) model\n\t */\n\tprotected final IModel<?> getInnermostModel(final IModel<?> model)\n\t{\n\t\tIModel<?> nested = model;\n\t\twhile (nested != null && nested instanceof IWrapModel)\n\t\t{\n\t\t\tfinal IModel<?> next = ((IWrapModel<?>)nested).getWrappedModel();\n\t\t\tif (nested == next)\n\t\t\t{\n\t\t\t\tthrow new WicketRuntimeException(\"Model for \" + nested + \" is self-referential\");\n\t\t\t}\n\t\t\tnested = next;\n\t\t}\n\t\treturn nested;\n\t}\n\n\t/**\n\t * Gets the component's current model comparator. Implementations can be used for testing the\n\t * current value of the components model data with the new value that is given.\n\t * \n\t * @return the value defaultModelComparator\n\t */\n\tpublic IModelComparator getModelComparator()\n\t{\n\t\treturn defaultModelComparator;\n\t}\n\n\t/**","sourceCodeStart":3776,"sourceCodeEnd":3812,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/org/apache/wicket/Component.java#L3776-L3812","documentation":"While unwrapping IWrapModel chains, Wicket detects a model whose getWrappedModel() returns itself, i.e. an infinite self-reference, and throws WicketRuntimeException 'Model for ... is self-referential'. This guard prevents StackOverflowError and infinite loops when resolving the innermost model.","triggerScenarios":"Implementing IWrapModel and returning `this` from getWrappedModel(); a wrapper model accidentally wiring itself as its own wrapped model during construction or configuration.","commonSituations":"Custom component-property-wrapping models where the constructor passes itself instead of the delegate; copy/paste mistakes in wrapper implementations; forms with wrapped models (IComponentInheritedModel) implemented incorrectly.","solutions":["Fix getWrappedModel() to return the actual delegate model, never this.","Ensure the inner model is created and passed into the wrapper's constructor.","Add an assertion/unit test that repeatedly unwrapping terminates."],"exampleFix":"// before\nclass MyWrapModel implements IWrapModel<String> {\n    public IModel<?> getWrappedModel() { return this; } // bug\n}\n// after\nclass MyWrapModel implements IWrapModel<String> {\n    private final IModel<String> inner;\n    MyWrapModel(IModel<String> inner) { this.inner = inner; }\n    public IModel<?> getWrappedModel() { return inner; }\n}","handlingStrategy":"validation","validationCode":"IModel<?> m = wrapper;\nint depth = 0;\nwhile (m instanceof IWrapModel) {\n    if (++depth > 100) throw new IllegalStateException(\"self-referential model\");\n    m = ((IWrapModel<?>) m).getWrappedModel();\n}","typeGuard":null,"tryCatchPattern":"try { resolveInnermostModel(model); } catch (WicketRuntimeException e) { log.error(\"self-referential model: {}\", e.getMessage()); }","preventionTips":["In IWrapModel implementations, never return this from getWrappedModel().","Store the delegate model in a final field assigned in the constructor.","Unit test unwrap termination for custom wrapper models."],"tags":["wicket","model","infinite-loop","bug"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}