{"record":{"id":"146830714eaa05cc","repo":"unslothai/unsloth","slug":"could-not-find-a-free-port-in-range-start-start","errorCode":null,"errorMessage":"Could not find a free port in range {start}-{start + max_attempts - 1}","messagePattern":"Could not find a free port in range (.+?)-(.+?)","errorType":"console","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/run.py","lineNumber":826,"sourceCode":"    host: str,\n    start: int,\n    max_attempts: int = 20,\n    avoid_own_studio: bool = False,\n) -> int:\n    \"\"\"Find a free port from `start`, trying up to max_attempts ports.\n\n    ``avoid_own_studio`` aborts rather than skipping past one of our own servers\n    in the fallback range, which would start a duplicate on a later port.\n    \"\"\"\n    for offset in range(max_attempts):\n        candidate = start + offset\n        if _is_port_free(host, candidate):\n            return candidate\n        if avoid_own_studio:\n            own = _own_studio_on_port(candidate, host)\n            if own is not None:\n                _abort_already_running(own, candidate)\n    raise RuntimeError(f\"Could not find a free port in range {start}-{start + max_attempts - 1}\")\n\n\nfrom utils.paths.storage_roots import studio_root as _studio_root\n\n# Legacy single-instance file; still read so `stop` finds an older build's server.\n_PID_FILE = _studio_root() / \"studio.pid\"\nPID_FILE_GLOB = \"studio-*.pid\"\n# Deliberately not a .pid: everything that globs PID_FILE_GLOB expects a bound\n# server with a port in the name, and a process that has not bound yet is not\n# one. Only the sibling probe reads these.\nSTARTUP_MARKER_GLOB = \"studio-starting-*.marker\"\n_OWN_STARTUP_MARKERS: \"list[Path]\" = []\n_STARTUP_MARKER_HOOK_REGISTERED = False\n\n\ndef _pid_file_for_port(port: int) -> Path:\n    # PID in the name: 127.0.0.1 and ::1 can share a port, and one file per port\n    # would let the second bind overwrite the first.","sourceCodeStart":808,"sourceCodeEnd":844,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/run.py#L808-L844","documentation":"RuntimeError from the port-picker in run.py: none of the max_attempts candidate ports starting at `start` were free (and, with avoid_own_studio, own-instance collisions abort earlier). Every offset in [start, start+max_attempts-1] was either occupied by another process or failed the bind probe.","triggerScenarios":"Starting Studio while many ports in the fallback range are taken (other services, a range consumed by ephemeral connections, or several Studio instances already running); a small max_attempts combined with a busy range; Docker port-publishing reserving the span.","commonSituations":"Dev machine with many local servers; Linux ip_local_port_range overlapping the Studio range so ephemeral sockets randomly occupy candidates; previous crashed runs leaving sockets in TIME_WAIT.","solutions":["Free or pick a specific port explicitly (pass an explicit --port outside the busy range).","Stop processes holding the range (ss -ltnp 'sport >= START' to identify them).","Widen the ephemeral gap or change the start port if the OS ephemeral range overlaps.","Retry after TIME_WAIT sockets expire (~60s) if a crash storm caused it."],"exampleFix":"# before: range busy\n$ unsloth studio run\n# RuntimeError: Could not find a free port in range 8000-8009\n\n# after: explicit free port\n$ ss -ltn 'sport >= 8000'\n$ unsloth studio run --port 8123","handlingStrategy":"validation","validationCode":"import socket\n\ndef port_free(host: str, port: int) -> bool:\n    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\n        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        return s.connect_ex((host, port)) != 0\n\nif not port_free('127.0.0.1', 8000):\n    raise SystemExit('port 8000 busy — pass a different --port')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass an explicit --port for scripted/CI launches instead of relying on range fallback","Audit listeners with ss -ltnp when the range is busy","Note Studio's own instances abort the scan deliberately — stop them rather than expecting a skip"],"tags":["startup","port-binding","network","configuration"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}