reflex-dev/reflex · error · TypeError

Background task must use `async with self` to modify state.

Error message

Background task must use `async with self` to modify state.

What it means

The StateProxy returned in background tasks only supports the async context manager protocol for acquiring mutability; `with self:` (sync) cannot await the underlying lock, so __enter__ unconditionally raises TypeError telling you to use `async with self`. This is a hard API guard: there is no sync path.

Source

Thrown at reflex/istate/proxy.py:210

                if self._self_mutable and self._self_actx is not None:
                    await self._self_actx.__aexit__(*exc_info)
            finally:
                self._self_actx = None
                self._self_mutable = False
                self._self_actx_lock_holder = None
                self._self_actx_lock.release()

    def __enter__(self):
        """Enter the regular context manager protocol.

        This is not supported for background tasks, and exists only to raise a more useful exception
        when the StateProxy is used incorrectly.

        Raises:
            TypeError: always, because only async contextmanager protocol is supported.
        """
        msg = "Background task must use `async with self` to modify state."
        raise TypeError(msg)

    def __exit__(self, *exc_info: Any) -> None:
        """Exit the regular context manager protocol.

        Args:
            exc_info: The exception info tuple.
        """

    def __getattr__(self, name: str) -> Any:
        """Get the attribute from the underlying state instance.

        Args:
            name: The name of the attribute.

        Returns:
            The value of the attribute.

        Raises:

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Change `with self:` to `async with self:` in background event handlers
  2. Ensure the enclosing handler is async (@rx.event(background=True) handlers are coroutines)
  3. Lint for `with self` inside async handlers (e.g. a custom ruff/pylint rule) if this recurs

Example fix

# before
@rx.event(background=True)
async def handler(self):
    with self:
        self.count += 1

# after
@rx.event(background=True)
async def handler(self):
    async with self:
        self.count += 1
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Writing `with self:` instead of `async with self:` inside an @rx.event(background=True) handler. Often a typo or muscle memory from sync code / older Reflex examples.

Common situations: Converting normal event handlers to background tasks and forgetting to switch the context keyword; IDE autocompleting `with`; porting code from other frameworks with sync context managers.

Related errors


AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28). Data as JSON: /api/errors/812cda5c17c10aec. Report an issue: GitHub.