{"record":{"id":"5b8d91a9ea27ce62","repo":"apache/dubbo","slug":"frameworkmodel-is-destroyed","errorCode":null,"errorMessage":"FrameworkModel is destroyed","messagePattern":"FrameworkModel is destroyed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java","lineNumber":295,"sourceCode":"    void tryDestroyProtocols() {\n        synchronized (instLock) {\n            if (pubApplicationModels.size() == 0) {\n                notifyProtocolDestroy();\n            }\n        }\n    }\n\n    void tryDestroy() {\n        synchronized (instLock) {\n            if (pubApplicationModels.size() == 0) {\n                destroy();\n            }\n        }\n    }\n\n    private void checkDestroyed() {\n        if (isDestroyed()) {\n            throw new IllegalStateException(\"FrameworkModel is destroyed\");\n        }\n    }\n\n    private void resetDefaultAppModel() {\n        synchronized (instLock) {\n            if (this.defaultAppModel != null && !this.defaultAppModel.isDestroyed()) {\n                return;\n            }\n            ApplicationModel oldDefaultAppModel = this.defaultAppModel;\n            if (pubApplicationModels.size() > 0) {\n                this.defaultAppModel = pubApplicationModels.get(0);\n            } else {\n                this.defaultAppModel = null;\n            }\n            if (defaultInstance == this && oldDefaultAppModel != this.defaultAppModel) {\n                if (LOGGER.isInfoEnabled()) {\n                    LOGGER.info(\"Reset global default application from \" + safeGetModelDesc(oldDefaultAppModel) + \" to \"\n                            + safeGetModelDesc(this.defaultAppModel));","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java#L277-L313","documentation":"Thrown by FrameworkModel.checkDestroyed() (a private guard invoked before mutating the model). It signals that the FrameworkModel has already completed its destroy lifecycle, so any attempt to obtain the default application model (defaultApplication()) or register a new application (addApplication()) is refused. The model tree is single-use: once destroyed it cannot be revived, and a fresh FrameworkModel must be created instead.","triggerScenarios":"Calling frameworkModel.defaultApplication() or frameworkModel.addApplication(...) after frameworkModel.destroy() has run. Also occurs when ApplicationModel.of(frameworkModel) is constructed against a destroyed framework, or when a background destroy thread races a re-initialization thread in test harnesses that reuse the same FrameworkModel.","commonSituations":"Unit/integration tests that call FrameworkModel.defaultModel().destroy() (or DubboBootstrap.getInstance().destroy()) in @AfterEach and then start a new DubboBootstrap in the next test without resetting the global default. Long-running apps that intentionally destroy and re-create the framework. Spring context refresh/destroy cycles where the FrameworkModel bean is scoped incorrectly (singleton reused across restarts).","solutions":["Do not reuse a destroyed FrameworkModel; create a new instance via `new FrameworkModel()` or let DubboBootstrap/FrameworkModel.defaultModel() lazily create a fresh one (destroy resets the global default).","In tests, ensure each test creates its own FrameworkModel/ApplicationModel and destroys it fully in teardown, or call FrameworkModel.destroyAll() to clear the global registry before the next test.","If using DubboBootstrap, start a new DubboBootstrap instance rather than calling methods on the one you destroyed.","Guard access with `if (!frameworkModel.isDestroyed())` before calling defaultApplication()/addApplication()."],"exampleFix":"// before\nFrameworkModel fm = FrameworkModel.defaultModel();\nfm.destroy();\nApplicationModel app = fm.defaultApplication(); // throws\n\n// after\nFrameworkModel fm = FrameworkModel.defaultModel();\nfm.destroy();\n// destroyed model resets the global default; a new one is created lazily\nApplicationModel app = FrameworkModel.defaultModel().defaultApplication();","handlingStrategy":"validation","validationCode":"if (frameworkModel == null || frameworkModel.isDestroyed()) {\n    frameworkModel = FrameworkModel.defaultModel(); // get/create a live model\n}\nApplicationModel app = frameworkModel.defaultApplication();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat FrameworkModel as single-use: never call mutating APIs after destroy().","In tests, destroy models in @AfterEach and let the next test obtain a fresh FrameworkModel.defaultModel().","Do not cache a FrameworkModel field across destroy/restart boundaries; re-resolve it.","Use DubboBootstrap to manage lifecycle rather than destroying models by hand."],"tags":["lifecycle","framework-model","destroy","test-isolation"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}