{"record":{"id":"eb9fac0dcea8897d","repo":"unslothai/unsloth","slug":"block-reason-or-not-settings-managed","errorCode":null,"errorMessage":"{block_reason} or not_settings_managed","messagePattern":"(.+?) or not_settings_managed","errorType":"exception","errorClass":"RuntimeError","httpStatus":409,"severity":"warning","filePath":"studio/backend/utils/remote_access_settings.py","lineNumber":312,"sourceCode":"    global _stop_worker, _stop_worker_admission\n    from cloudflare_tunnel import (\n        capture_studio_tunnel_start_admission,\n        get_studio_tunnel_control_token,\n    )\n\n    admission = capture_studio_tunnel_start_admission()\n    if admission is None:\n        raise RuntimeError(\"server_shutting_down\")\n    status = remote_access_status(app_state)\n    current = get_studio_tunnel_control_token()\n    if current[0] != admission[0]:\n        raise RuntimeError(\"server_lifecycle_changed\")\n    if status[\"state\"] == \"off\" and status[\"managed_by\"] is None:\n        return status\n    if status[\"state\"] == \"stopping\" and status[\"managed_by\"] == \"settings\":\n        return status\n    if status[\"managed_by\"] != \"settings\":\n        raise RuntimeError(status[\"block_reason\"] or \"not_settings_managed\")\n\n    if get_studio_tunnel_control_token() != admission:\n        raise RuntimeError(\"server_lifecycle_changed\")\n\n    def _stop() -> None:\n        global _stop_worker_admission\n        from cloudflare_tunnel import get_studio_tunnel_status, stop_studio_tunnel\n\n        # A stop can beat the newly-created start worker to the controller. Wait\n        # until it claims settings ownership, then cancel that generation. Bounded:\n        # a start that never claims it (foreign owner, bailed on admission) must\n        # not defer the user's Stop for the probe deadline.\n        deadline = time.monotonic() + _STOP_OWNERSHIP_WAIT\n        while _worker_alive(_start_worker) and time.monotonic() < deadline:\n            if get_studio_tunnel_status()[\"managed_by\"] == \"settings\":\n                break\n            time.sleep(0.02)\n        current = get_studio_tunnel_control_token()","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/remote_access_settings.py#L294-L330","documentation":"Raised by stop_remote_access() when the tunnel is not managed by 'settings' — status['managed_by'] is something else (e.g. an auto-start flow or a foreign owner). The message is status['block_reason'] when set, otherwise the literal 'not_settings_managed'. Settings-owned stop only cancels settings-owned tunnels; already-off/stopping states return idempotently instead of raising.","triggerScenarios":"Calling stop_remote_access() while managed_by is neither 'settings' nor None-with-state-off — e.g. the tunnel was started by the auto-start preference flow, an external tool, or another component that claimed ownership.","commonSituations":"Auto-start enabled at boot starts the tunnel under a different owner; user later tries to stop it via the settings toggle and hits this. Or an external cloudflared instance was wired in manually.","solutions":["Read block_reason in the error — it identifies the owning flow.","Stop the tunnel through its owner: disable the auto-start preference for boot-owned tunnels, or use the owning component's stop path.","Only use stop_remote_access() for tunnels the settings UI itself started (managed_by == 'settings')."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"status = remote_access_status(app_state)\nif status['managed_by'] != 'settings':\n    abort(409, f\"tunnel managed by {status['managed_by'] or 'another owner'}; \"\n               f\"{status['block_reason'] or 'stop it from its owning flow'}\")","typeGuard":"def is_settings_managed(status: dict) -> bool:\n    return status.get('managed_by') == 'settings'","tryCatchPattern":"try:\n    stop_remote_access(app_state)\nexcept RuntimeError as e:\n    msg = str(e)\n    if msg == 'not_settings_managed' or 'managed' in msg:\n        # route to the owner: disable auto-start pref or use the owning component's stop\n        disable_tunnel_autostart()\n    else:\n        raise","preventionTips":["Read managed_by in status before choosing Start vs Stop from the settings UI.","Remember: tunnels started by the auto-start preference are not settings-owned; stop them by changing that preference."],"tags":["ownership","state-machine","tunnel","remote-access","python"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}