{"record":{"id":"5ce18a7d043f8c7a","repo":"pallets/flask","slug":"cannot-register-a-blueprint-on-itself","errorCode":null,"errorMessage":"Cannot register a blueprint on itself","messagePattern":"Cannot register a blueprint on itself","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/flask/sansio/blueprints.py","lineNumber":270,"sourceCode":"        \"\"\"\n        return BlueprintSetupState(self, app, options, first_registration)\n\n    @setupmethod\n    def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None:\n        \"\"\"Register a :class:`~flask.Blueprint` on this blueprint. Keyword\n        arguments passed to this method will override the defaults set\n        on the blueprint.\n\n        .. versionchanged:: 2.0.1\n            The ``name`` option can be used to change the (pre-dotted)\n            name the blueprint is registered with. This allows the same\n            blueprint to be registered multiple times with unique names\n            for ``url_for``.\n\n        .. versionadded:: 2.0\n        \"\"\"\n        if blueprint is self:\n            raise ValueError(\"Cannot register a blueprint on itself\")\n        self._blueprints.append((blueprint, options))\n\n    def register(self, app: App, options: dict[str, t.Any]) -> None:\n        \"\"\"Called by :meth:`Flask.register_blueprint` to register all\n        views and callbacks registered on the blueprint with the\n        application. Creates a :class:`.BlueprintSetupState` and calls\n        each :meth:`record` callback with it.\n\n        :param app: The application this blueprint is being registered\n            with.\n        :param options: Keyword arguments forwarded from\n            :meth:`~Flask.register_blueprint`.\n\n        .. versionchanged:: 2.3\n            Nested blueprints now correctly apply subdomains.\n\n        .. versionchanged:: 2.1\n            Registering the same blueprint with the same name multiple","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/pallets/flask/blob/3596b1ab61cea85edb8970e83ff61daa073facf8/src/flask/sansio/blueprints.py#L252-L288","documentation":"register_blueprint on a Scaffold checks `if blueprint is self` and raises ValueError to prevent infinite recursion during registration, since registering a blueprint on itself would create a self-referential registration cycle.","triggerScenarios":"Calling bp.register_blueprint(bp); a generic loop that pairs blueprints from a list with themselves; programmatic registration where the parent and child reference resolve to the same object.","commonSituations":"Automated blueprint auto-discovery that accidentally registers a blueprint as its own child; refactoring a blueprint hierarchy that left a self-reference; copy-paste error.","solutions":["Skip self-registration: if blueprint is not bp: bp.register_blueprint(blueprint).","Fix the registration list/logic so a blueprint is never both parent and child.","Validate the input collection before the registration loop."],"exampleFix":"// before\nfor child in blueprints:\n    bp.register_blueprint(child)  # child may equal bp\n\n// after\nfor child in blueprints:\n    if child is not bp:\n        bp.register_blueprint(child)","handlingStrategy":"type-guard","validationCode":"def safe_register(parent, child, options):\n    if child is parent:\n        raise ValueError('cannot register blueprint on itself')\n    parent.register_blueprint(child, **options)\n","typeGuard":"def is_not_self(parent, child) -> bool:\n    return child is not parent\n","tryCatchPattern":null,"preventionTips":["Guard auto-registration loops with `if child is not parent`.","Keep parent/child blueprint collections disjoint.","Unit-test blueprint registration with a self-injection case."],"tags":["flask","blueprint","validation","recursion"],"backgroundTag":null,"analyzedSha":"3596b1ab61cea85edb8970e83ff61daa073facf8","analyzedAt":"2026-08-11T20:11:52.622Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}