reflex-dev/reflex · error · UntrackedLocalVarError

{local_name!r} is not tracked in the current scope.

Error message

{local_name!r} is not tracked in the current scope.

What it means

The dependency tracker walks bytecode and only understands locals it has recorded (function args, assignments, comprehensions). Accessing a local name it never tracked raises UntrackedLocalVarError.

Source

Thrown at packages/reflex-base/src/reflex_base/vars/dep_tracking.py:146

    def get_tracked_local(self, local_name: str) -> type[BaseState] | ModuleType:
        """Get the value of a local name tracked in the current function scope.

        Args:
            local_name: The name of the local variable to fetch.

        Returns:
            The value of local name tracked in the current scope (a referenced
            BaseState subclass or imported module).

        Raises:
            UntrackedLocalVarError: If the local variable is not being tracked.
        """
        try:
            local_value = self.tracked_locals[local_name]
        except KeyError as ke:
            msg = f"{local_name!r} is not tracked in the current scope."
            raise UntrackedLocalVarError(msg) from ke
        return local_value

    def load_attr_or_method(self, instruction: dis.Instruction) -> None:
        """Handle loading an attribute or method from the object on top of the stack.

        This method directly tracks attributes and recursively merges
        dependencies from analyzing the dependencies of any methods called.

        Args:
            instruction: The dis instruction to process.

        Raises:
            VarValueError: if the attribute is an disallowed name or attribute
                does not reference a BaseState.
        """
        from .base import ComputedVar

        if instruction.argval in self.INVALID_NAMES:

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Simplify the computed var: reference state attributes directly (self.other.value) so tracking works
  2. Move complex logic into a plain (non-cached, non-tracked) helper and pass explicit values
  3. Explicitly declare deps=[...] so automatic tracking is not required
  4. Report the pattern upstream if it looks like valid code the tracker should support

Example fix

# before
@rx.memo
def full(self):
    name = format_name(self.first, self.last)  # helper confuses tracker
    return name
# after
@rx.memo
def full(self):
    return f"{self.first} {self.last}"
Defensive patterns

Strategy: fallback

Try / catch

from reflex.vars.dep_tracking import UntrackedLocalVarError
try:
    @rx.memo
    def v(self): return complex_helper(self.a, self.b)
except UntrackedLocalVarError:
    @rx.memo(deps=[State.a, State.b])
    def v(self): return complex_helper(self.a, self.b)

Prevention

When it happens

Trigger: A cached computed var that references a closure variable, imported symbol used as a local, or an exotic bytecode pattern the tracker does not model, then calls get_tracked_local for that name.

Common situations: Cached computed vars using complex helpers, lambdas, walrus edge cases, or language features newer than the tracker supports.

Related errors


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