{"record":{"id":"9d9005ec6bae233a","repo":"aio-libs/aiohttp","slug":"cannot-add-frozen-application","errorCode":null,"errorMessage":"Cannot add frozen application","messagePattern":"Cannot add frozen application","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_app.py","lineNumber":290,"sourceCode":"        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)\n\n    def add_routes(self, routes: Iterable[AbstractRouteDef]) -> list[AbstractRoute]:","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_app.py#L272-L308","documentation":"Raised by Application._add_subapp when the subapp being attached is already frozen. A subapp is frozen by aiohttp as part of mounting (see _add_subapp calls subapp.pre_freeze()), so passing an already-frozen subapp means it was either previously mounted elsewhere or explicitly frozen, and re-mounting would double-freeze or share mutable routing state. The check uses subapp.frozen.","triggerScenarios":"Passing the same subapp instance to add_subapp twice (mounting it under two parents); mounting a subapp that was already attached as a child of another app; manually freezing a subapp then trying to mount it.","commonSituations":"Reusing a single Application object across multiple parents for code sharing; building a subapp once and registering it in a loop; refactoring that moves a subapp without recreating it.","solutions":["Create a fresh Application instance for each mount; do not reuse a subapp across parents.","If you need the same routes under multiple prefixes, use a factory function that builds a new Application each call.","Ensure add_subapp is called exactly once per subapp instance."],"exampleFix":"# before\nshared = web.Application()\napp.add_subapp('/a', shared)\napp.add_subapp('/b', shared)  # raises: already frozen\n\n# after\ndef make_sub():\n    sub = web.Application()\n    sub.add_routes(...)\n    return sub\napp.add_subapp('/a', make_sub())\napp.add_subapp('/b', make_sub())","handlingStrategy":"validation","validationCode":"if subapp.frozen:\n    raise RuntimeError('subapp already mounted; create a fresh instance')\napp.add_subapp(prefix, subapp)","typeGuard":"def subapp_mountable(subapp) -> bool:\n    return not getattr(subapp, 'frozen', False)","tryCatchPattern":null,"preventionTips":["Use a factory to build a new Application for each mount.","Never reuse one subapp instance under multiple parents.","Call add_subapp exactly once per subapp instance."],"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"}