{"record":{"id":"e89c6f08f00745bb","repo":"reflex-dev/reflex","slug":"the-lock-warning-threshold-self-lock-warning-thre","errorCode":null,"errorMessage":"The lock warning threshold({self.lock_warning_threshold}) must be less than the lock expiration time({lock_expiration}).","messagePattern":"The lock warning threshold\\((.+?)\\) must be less than the lock expiration time\\((.+?)\\)\\.","errorType":"exception","errorClass":"InvalidLockWarningThresholdError","httpStatus":null,"severity":"error","filePath":"reflex/istate/manager/redis.py","lineNumber":205,"sourceCode":"        init=False,\n    )\n    _lock_task: asyncio.Task | None = dataclasses.field(default=None, init=False)\n\n    # Whether debug prints are enabled.\n    _debug_enabled: bool = dataclasses.field(\n        default=environment.REFLEX_STATE_MANAGER_REDIS_DEBUG.get(),\n        init=False,\n    )\n\n    def __post_init__(self):\n        \"\"\"Validate the lock warning threshold.\n\n        Raises:\n            InvalidLockWarningThresholdError: If the lock warning threshold is invalid.\n        \"\"\"\n        if self.lock_warning_threshold >= (lock_expiration := self.lock_expiration):\n            msg = f\"The lock warning threshold({self.lock_warning_threshold}) must be less than the lock expiration time({lock_expiration}).\"\n            raise InvalidLockWarningThresholdError(msg)\n        if self._oplock_enabled and self.oplock_hold_time_ms >= lock_expiration:\n            msg = f\"The opportunistic lock hold time({self.oplock_hold_time_ms}) must be less than the lock expiration time({lock_expiration}).\"\n            raise InvalidLockWarningThresholdError(msg)\n        with contextlib.suppress(RuntimeError):\n            asyncio.get_running_loop()  # Check if we're in an event loop.\n            self._ensure_lock_task()\n\n    def _get_required_state_classes(\n        self,\n        target_state_cls: type[BaseState],\n        subclasses: bool = False,\n        required_state_classes: set[type[BaseState]] | None = None,\n    ) -> set[type[BaseState]]:\n        \"\"\"Recursively determine which states are required to fetch the target state.\n\n        This will always include potentially dirty substates that depend on vars\n        in the target_state_cls.\n","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/reflex/istate/manager/redis.py#L187-L223","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set lock_warning_threshold strictly below lock_expiration (e.g. expiration=60, warning=55)","If you need a higher threshold, increase lock_expiration first, then keep the threshold under it","For long-running work, keep lock times modest and move the work into @rx.event(background=True) instead"],"exampleFix":"# before\nrx.App(state_manager=rx.state.StateManagerDisk? no - StateManagerRedis(\n    lock_expiration=30, lock_warning_threshold=30))\n\n# after\nrx.App(state_manager=StateManagerRedis(lock_expiration=30, lock_warning_threshold=25))","handlingStrategy":"validation","validationCode":"assert sm.lock_warning_threshold < sm.lock_expiration, (\n    f\"warning ({sm.lock_warning_threshold}) must be < expiration ({sm.lock_expiration})\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive the warning threshold from expiration in config (e.g. lock_expiration * 0.9)","Centralize state manager config in one place instead of scattering literals","Add a startup config sanity test for lock values"],"tags":["reflex","redis","state-manager","config-validation","locking"],"backgroundTag":"config-validation-failed","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}