{"record":{"id":"bd99cc362a14932d","repo":"reflex-dev/reflex","slug":"background-task-stateproxy-is-immutable-outside-of","errorCode":null,"errorMessage":"Background task StateProxy is immutable outside of a context manager. Use `async with self` to modify state.","messagePattern":"Background task StateProxy is immutable outside of a context manager\\. Use `async with self` to modify state\\.","errorType":"exception","errorClass":"ImmutableStateError","httpStatus":null,"severity":"error","filePath":"reflex/istate/proxy.py","lineNumber":236,"sourceCode":"\n    def __getattr__(self, name: str) -> Any:\n        \"\"\"Get the attribute from the underlying state instance.\n\n        Args:\n            name: The name of the attribute.\n\n        Returns:\n            The value of the attribute.\n\n        Raises:\n            ImmutableStateError: If the state is not in mutable mode.\n        \"\"\"\n        if name in [\"substates\", \"parent_state\"] and not self._is_mutable():\n            msg = (\n                \"Background task StateProxy is immutable outside of a context \"\n                \"manager. Use `async with self` to modify state.\"\n            )\n            raise ImmutableStateError(msg)\n\n        value = super().__getattr__(name)  # pyright: ignore[reportAttributeAccessIssue]\n        if not name.startswith(\"_self_\") and isinstance(value, MutableProxy):\n            # ensure mutations to these containers are blocked unless proxy is _mutable\n            return ImmutableMutableProxy(\n                wrapped=value.__wrapped__,\n                state=self,\n                field_name=value._self_field_name,\n            )\n        if isinstance(value, functools.partial) and value.args[0] is self.__wrapped__:\n            # Rebind event handler to the proxy instance\n            value = functools.partial(\n                value.func,\n                self,\n                *value.args[1:],\n                **value.keywords,\n            )\n        if isinstance(value, MethodType) and value.__self__ is self.__wrapped__:","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/reflex/istate/proxy.py#L218-L254","documentation":"In a background task, the StateProxy is immutable outside an `async with self` block. Accessing the special attributes substates or parent_state while immutable raises ImmutableStateError, because traversing the state tree could bypass mutation guards (a substate proxy obtained this way would appear mutable). Regular attribute reads are wrapped in immutable proxies; these two tree-navigation attributes are blocked outright.","triggerScenarios":"Inside @rx.event(background=True), reading self.substates or self.parent_state outside any `async with self:` block — e.g. logging the tree, finding a sibling state via self.parent_state.substates[...] to mutate it.","commonSituations":"Trying to reach another substate from a background handler by walking parent_state/substates instead of using app.state_manager or rx.app.get_state refactors; debugging code that prints self.substates; moving tree-navigation logic that worked in normal handlers into background tasks.","solutions":["Move the substates/parent_state access inside an `async with self:` block","To access a different state from a background task, obtain it via the state manager (e.g. app.state_manager.modify_state(BaseStateToken(...))) or pass it in, rather than walking the tree","Restructure so the background task operates only on its own state fields"],"exampleFix":"# before\n@rx.event(background=True)\nasync def handler(self):\n    sibling = self.parent_state.substates[\"other\"]  # ImmutableStateError\n\n# after\n@rx.event(background=True)\nasync def handler(self):\n    async with self:\n        sibling = self.parent_state.substates[\"other\"]\n        sibling.value = 1","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"# inside a background task, check mutability before tree access\nif proxy._is_mutable():\n    sub = proxy.parent_state.substates  # ok inside `async with self`\nelse:\n    # defer until inside `async with self`","tryCatchPattern":"from reflex.istate.proxy import ImmutableStateError\ntry:\n    subs = self.substates\nexcept ImmutableStateError:\n    async with self:\n        subs = self.substates  # now safe","preventionTips":["Do all substates/parent_state navigation inside `async with self`","Get sibling states via the state manager instead of walking the tree from a background proxy","Keep tree-navigation logic out of background tasks where possible"],"tags":["reflex","background-task","state-proxy","immutability","state-tree"],"backgroundTag":"immutable-state-access","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}