reflex-dev/reflex · error · InvalidLockWarningThresholdError

The lock warning threshold({self.lock_warning_threshold}) mu

Error message

The lock warning threshold({self.lock_warning_threshold}) must be less than the lock expiration time({lock_expiration}).

What it means

The Redis state manager validates its lock configuration in __post_init__ and requires lock_warning_threshold to be strictly less than lock_expiration. The warning threshold only makes sense if it fires before the lock expires; otherwise the warning could never trigger in time. Raised as InvalidLockWarningThresholdError at construction time, so the app fails fast at startup.

Source

Thrown at reflex/istate/manager/redis.py:205

        init=False,
    )
    _lock_task: asyncio.Task | None = dataclasses.field(default=None, init=False)

    # Whether debug prints are enabled.
    _debug_enabled: bool = dataclasses.field(
        default=environment.REFLEX_STATE_MANAGER_REDIS_DEBUG.get(),
        init=False,
    )

    def __post_init__(self):
        """Validate the lock warning threshold.

        Raises:
            InvalidLockWarningThresholdError: If the lock warning threshold is invalid.
        """
        if self.lock_warning_threshold >= (lock_expiration := self.lock_expiration):
            msg = f"The lock warning threshold({self.lock_warning_threshold}) must be less than the lock expiration time({lock_expiration})."
            raise InvalidLockWarningThresholdError(msg)
        if self._oplock_enabled and self.oplock_hold_time_ms >= lock_expiration:
            msg = f"The opportunistic lock hold time({self.oplock_hold_time_ms}) must be less than the lock expiration time({lock_expiration})."
            raise InvalidLockWarningThresholdError(msg)
        with contextlib.suppress(RuntimeError):
            asyncio.get_running_loop()  # Check if we're in an event loop.
            self._ensure_lock_task()

    def _get_required_state_classes(
        self,
        target_state_cls: type[BaseState],
        subclasses: bool = False,
        required_state_classes: set[type[BaseState]] | None = None,
    ) -> set[type[BaseState]]:
        """Recursively determine which states are required to fetch the target state.

        This will always include potentially dirty substates that depend on vars
        in the target_state_cls.

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Set lock_warning_threshold strictly below lock_expiration (e.g. expiration=60, warning=55)
  2. If you need a higher threshold, increase lock_expiration first, then keep the threshold under it
  3. For long-running work, keep lock times modest and move the work into @rx.event(background=True) instead

Example fix

# before
rx.App(state_manager=rx.state.StateManagerDisk? no - StateManagerRedis(
    lock_expiration=30, lock_warning_threshold=30))

# after
rx.App(state_manager=StateManagerRedis(lock_expiration=30, lock_warning_threshold=25))
Defensive patterns

Strategy: validation

Validate before calling

assert sm.lock_warning_threshold < sm.lock_expiration, (
    f"warning ({sm.lock_warning_threshold}) must be < expiration ({sm.lock_expiration})")

Prevention

When it happens

Trigger: Instantiating StateManager(backend="redis", lock_expiration=..., lock_warning_threshold=...) where lock_warning_threshold >= lock_expiration. Defaults are fine; this happens when a user customizes rx.App(state_manager=...) or environment-driven config and sets the warning threshold equal to or above the expiration.

Common situations: Tuning lock times for long-running events: raising lock_warning_threshold without raising lock_expiration proportionally; copying config between apps with different lock_expiration values; setting both to the same number assuming >= is allowed.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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