unslothai/unsloth · warning · RuntimeError
{block_reason} or not_settings_managed
Error message
{block_reason} or not_settings_managed What it means
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.
Source
Thrown at studio/backend/utils/remote_access_settings.py:312
global _stop_worker, _stop_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["state"] == "off" and status["managed_by"] is None:
return status
if status["state"] == "stopping" and status["managed_by"] == "settings":
return status
if status["managed_by"] != "settings":
raise RuntimeError(status["block_reason"] or "not_settings_managed")
if get_studio_tunnel_control_token() != admission:
raise RuntimeError("server_lifecycle_changed")
def _stop() -> None:
global _stop_worker_admission
from cloudflare_tunnel import get_studio_tunnel_status, stop_studio_tunnel
# A stop can beat the newly-created start worker to the controller. Wait
# until it claims settings ownership, then cancel that generation. Bounded:
# a start that never claims it (foreign owner, bailed on admission) must
# not defer the user's Stop for the probe deadline.
deadline = time.monotonic() + _STOP_OWNERSHIP_WAIT
while _worker_alive(_start_worker) and time.monotonic() < deadline:
if get_studio_tunnel_status()["managed_by"] == "settings":
break
time.sleep(0.02)
current = get_studio_tunnel_control_token()View on GitHub (pinned to 203007d190)
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').
Defensive patterns
Strategy: validation
Validate before calling
status = remote_access_status(app_state)
if status['managed_by'] != 'settings':
abort(409, f"tunnel managed by {status['managed_by'] or 'another owner'}; "
f"{status['block_reason'] or 'stop it from its owning flow'}") Type guard
def is_settings_managed(status: dict) -> bool:
return status.get('managed_by') == 'settings' Try / catch
try:
stop_remote_access(app_state)
except RuntimeError as e:
msg = str(e)
if msg == 'not_settings_managed' or 'managed' in msg:
# route to the owner: disable auto-start pref or use the owning component's stop
disable_tunnel_autostart()
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- {block_reason} or operation_in_progress
- server_shutting_down
- server_lifecycle_changed
- server_port_unavailable
- Authorization callback was already used.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/eb9fac0dcea8897d.
Report an issue: GitHub.