{"record":{"id":"694103246839f0b9","repo":"aio-libs/aiohttp","slug":"cannot-add-sub-application-to-frozen-application","errorCode":null,"errorMessage":"Cannot add sub application to frozen application","messagePattern":"Cannot add sub application to frozen application","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_app.py","lineNumber":288,"sourceCode":"\n        reg_handler(\"on_startup\")\n        reg_handler(\"on_shutdown\")\n        reg_handler(\"on_cleanup\")\n\n    def add_subapp(self, prefix: str, subapp: \"Application\") -> PrefixedSubAppResource:\n        if not isinstance(prefix, str):\n            raise TypeError(\"Prefix must be str\")\n        prefix = prefix.rstrip(\"/\")\n        if not prefix:\n            raise ValueError(\"Prefix cannot be empty\")\n        factory = partial(PrefixedSubAppResource, prefix, subapp)\n        return self._add_subapp(factory, subapp)\n\n    def _add_subapp(\n        self, resource_factory: Callable[[], _Resource], subapp: \"Application\"\n    ) -> _Resource:\n        if self.frozen:\n            raise RuntimeError(\"Cannot add sub application to frozen application\")\n        if subapp.frozen:\n            raise RuntimeError(\"Cannot add frozen application\")\n        resource = resource_factory()\n        self.router.register_resource(resource)\n        self._reg_subapp_signals(subapp)\n        self._subapps.append(subapp)\n        subapp.pre_freeze()\n        return resource\n\n    def add_domain(self, domain: str, subapp: \"Application\") -> MatchedSubAppResource:\n        if not isinstance(domain, str):\n            raise TypeError(\"Domain must be str\")\n        elif \"*\" in domain:\n            rule: Domain = MaskDomain(domain)\n        else:\n            rule = Domain(domain)\n        factory = partial(MatchedSubAppResource, rule, subapp)\n        return self._add_subapp(factory, subapp)","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_app.py#L270-L306","documentation":"Raised by Application._add_subapp when the parent application is already frozen. Once an app is frozen (during startup or when itself added as a subapp), its router and subapp list are immutable, so adding a new subapp would not be reflected in the live routing table and could violate the freeze contract. The check uses self.frozen.","triggerScenarios":"Calling app.add_subapp(...) after web.run_app has started, or inside an on_startup handler that runs after freeze, or on an app that was already attached as a subapp elsewhere.","commonSituations":"Dynamically registering sub-apps from startup hooks that fire post-freeze; attempting to add routes/subapps from within a request handler; ordering on_startup callbacks such that add_subapp runs after the app freeze step.","solutions":["Register all subapps before starting the server, i.e. at module load time or in an on_startup handler that runs before freeze.","If dynamic mounting is required, restructure so subapps are known at startup, or rebuild and restart the app.","Check app.frozen before calling add_subapp and surface a clear error."],"exampleFix":"# before\nasync def late_startup(app):\n    app.add_subapp('/late', sub)  # parent already frozen\napp.on_startup.append(late_startup)\n\n# after\napp.add_subapp('/late', sub)  # register at module load, before run_app","handlingStrategy":"validation","validationCode":"if app.frozen:\n    raise RuntimeError('cannot add subapp after startup')\napp.add_subapp(prefix, subapp)","typeGuard":"def app_accepts_subapps(app) -> bool:\n    return not getattr(app, 'frozen', False)","tryCatchPattern":null,"preventionTips":["Register all subapps at module load time, before run_app.","Order on_startup callbacks so mounting happens pre-freeze.","Never call add_subapp from request handlers."],"tags":["web","subapp","lifecycle","frozen"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}