unslothai/unsloth · warning · RuntimeError

{block_reason} or operation_in_progress

Error message

{block_reason} or operation_in_progress

What it means

Raised by start_remote_access() when remote_access_status(app_state) reports can_start == false. The message is status['block_reason'] if present, otherwise the generic 'operation_in_progress' — so the error text is dynamic and names the actual blocker (e.g. another operation owns the tunnel) or defaults to operation_in_progress.

Source

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

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)
        if url:
            logger.info("Secure link access via Cloudflare: %s", url)

    _open_remote_access_stop_response_admission()
    with _worker_lock:
        if not _worker_is_current(_start_worker, _start_worker_admission, admission):
            _start_worker = threading.Thread(target = _start, daemon = True)
            _start_worker_admission = admission

View on GitHub (pinned to 203007d190)

Solutions

  1. Read the block_reason in the error/status — it names the specific owner or transition blocking the start.
  2. Wait for the in-flight operation to settle (poll remote_access_status until can_start is true), then retry.
  3. If a foreign owner holds the tunnel, stop it through its owning flow first or change the auto-start preference instead of forcing a settings start.
Defensive patterns

Strategy: retry

Validate before calling

status = remote_access_status(app_state)
if not status['can_start']:
    abort(409, status['block_reason'] or 'operation in progress')

Try / catch

try:
    start_remote_access(app_state)
except RuntimeError as e:
    msg = str(e)
    if msg == 'operation_in_progress':
        wait_for(lambda: remote_access_status(app_state)['can_start'], timeout=30)
        start_remote_access(app_state)
    else:
        raise  # block_reason names a real owner; resolve that instead

Prevention

When it happens

Trigger: Calling start_remote_access() while the tunnel state machine cannot accept a start: a stop is mid-flight, the tunnel is in 'stopping' state, or another owner (not 'settings') currently manages the tunnel. Idempotent re-starts are NOT blocked (state 'starting'/'online' with managed_by 'settings' returns the status instead).

Common situations: User toggles Stop then immediately Start; the stop worker is still tearing the tunnel down. Or an auto-start flow (managed_by other than 'settings') owns the tunnel and a manual settings start is attempted.

Related errors


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