unslothai/unsloth · warning · RuntimeError

server_shutting_down

Error message

server_shutting_down

What it means

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.

Source

Thrown at studio/backend/utils/remote_access_settings.py:261

        # documents that those do not support Server-Sent Events. Measured: an
        # SSE endpoint returns 200 with text/event-stream through the tunnel but
        # delivers no events. So responses are only streamable while no tunnel
        # is carrying them.
        "streaming_supported": status["url"] is None,
    }


def start_remote_access(app_state) -> dict:
    """Schedule a settings-owned start. Repeated requests are idempotent."""
    global _start_worker, _start_worker_admission
    from cloudflare_tunnel import (
        capture_studio_tunnel_start_admission,
        get_studio_tunnel_control_token,
    )

    admission = capture_studio_tunnel_start_admission()
    if admission is None:
        raise RuntimeError("server_shutting_down")
    status = remote_access_status(app_state)
    current = get_studio_tunnel_control_token()
    if current[0] != admission[0]:
        raise RuntimeError("server_lifecycle_changed")
    if status["managed_by"] == "settings" and status["state"] in {"starting", "online"}:
        return status
    if not status["can_start"]:
        raise RuntimeError(status["block_reason"] or "operation_in_progress")

    port = getattr(app_state, "remote_access_port", None)
    if not isinstance(port, int) or port <= 0:
        raise RuntimeError("server_port_unavailable")
    if get_studio_tunnel_control_token() != admission:
        raise RuntimeError("server_lifecycle_changed")

    def _start() -> None:
        from cloudflare_tunnel import start_studio_tunnel
        url = start_studio_tunnel(port, managed_by = "settings", admission = admission)

View on GitHub (pinned to 203007d190)

Solutions

  1. Wait for the server restart to finish, then re-issue the start request — the new process captures admissions normally.
  2. If using the API, treat 'server_shutting_down' as a transient signal and retry with backoff once the health endpoint responds.
  3. Check server logs to confirm why it was shutting down (update applied, SIGTERM, crash) if the shutdown was unexpected.
Defensive patterns

Strategy: retry

Validate before calling

def server_healthy() -> bool:
    try:
        return requests.get(f'{base}/health', timeout=2).ok
    except requests.RequestException:
        return False

Try / catch

try:
    start_remote_access(app_state)
except RuntimeError as e:
    if str(e) == 'server_shutting_down':
        wait_until(server_healthy, timeout=60)
        start_remote_access(app_state)  # fresh process, fresh admission
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/97efbf74a64dabac. Report an issue: GitHub.