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 = admissionView on GitHub (pinned to 203007d190)
Solutions
- Read the block_reason in the error/status — it names the specific owner or transition blocking the start.
- Wait for the in-flight operation to settle (poll remote_access_status until can_start is true), then retry.
- 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
- Poll remote_access_status()['can_start'] before issuing Start.
- Disable the Start button while a Stop (or any transition) is pending in the UI.
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
- server_shutting_down
- server_lifecycle_changed
- {block_reason} or not_settings_managed
- server_port_unavailable
- MLXInferenceBackend cannot load GGUF model '{model_name}': G
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/43cf65f30498c260.
Report an issue: GitHub.