{"record":{"id":"97efbf74a64dabac","repo":"unslothai/unsloth","slug":"server-shutting-down","errorCode":null,"errorMessage":"server_shutting_down","messagePattern":"server_shutting_down","errorType":"exception","errorClass":"RuntimeError","httpStatus":409,"severity":"warning","filePath":"studio/backend/utils/remote_access_settings.py","lineNumber":261,"sourceCode":"        # documents that those do not support Server-Sent Events. Measured: an\n        # SSE endpoint returns 200 with text/event-stream through the tunnel but\n        # delivers no events. So responses are only streamable while no tunnel\n        # is carrying them.\n        \"streaming_supported\": status[\"url\"] is None,\n    }\n\n\ndef start_remote_access(app_state) -> dict:\n    \"\"\"Schedule a settings-owned start. Repeated requests are idempotent.\"\"\"\n    global _start_worker, _start_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[\"managed_by\"] == \"settings\" and status[\"state\"] in {\"starting\", \"online\"}:\n        return status\n    if not status[\"can_start\"]:\n        raise RuntimeError(status[\"block_reason\"] or \"operation_in_progress\")\n\n    port = getattr(app_state, \"remote_access_port\", None)\n    if not isinstance(port, int) or port <= 0:\n        raise RuntimeError(\"server_port_unavailable\")\n    if get_studio_tunnel_control_token() != admission:\n        raise RuntimeError(\"server_lifecycle_changed\")\n\n    def _start() -> None:\n        from cloudflare_tunnel import start_studio_tunnel\n        url = start_studio_tunnel(port, managed_by = \"settings\", admission = admission)","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/remote_access_settings.py#L243-L279","documentation":"Raised by start_remote_access() when capture_studio_tunnel_start_admission() returns None, meaning the server is in (or entering) shutdown. Admission tokens gate tunnel start/stop operations so no new tunnel worker is spawned on a dying process. This is a lifecycle-state error, not a tunnel failure — retrying after shutdown completes (or on restart) is the path forward.","triggerScenarios":"Calling start_remote_access(app_state) while the studio server process is shutting down: the admission capture returns None the moment shutdown begins, so any racing Start request from the settings UI or API gets this RuntimeError.","commonSituations":"A user clicks 'enable secure link' in the settings page at the same moment the server is restarting (update flow, manual restart, or crash). Automation scripts issuing start calls during a deployment window.","solutions":["Wait for the server restart to finish, then re-issue the start request — the new process captures admissions normally.","If using the API, treat 'server_shutting_down' as a transient signal and retry with backoff once the health endpoint responds.","Check server logs to confirm why it was shutting down (update applied, SIGTERM, crash) if the shutdown was unexpected."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"def server_healthy() -> bool:\n    try:\n        return requests.get(f'{base}/health', timeout=2).ok\n    except requests.RequestException:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    start_remote_access(app_state)\nexcept RuntimeError as e:\n    if str(e) == 'server_shutting_down':\n        wait_until(server_healthy, timeout=60)\n        start_remote_access(app_state)  # fresh process, fresh admission\n    else:\n        raise","preventionTips":["Disable remote-access controls while a restart/update is known to be in flight.","Treat lifecycle errors as distinct from tunnel errors in clients: retry the former, surface the latter."],"tags":["lifecycle","tunnel","remote-access","transient","python"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}