{"record":{"id":"e5fcbae4a14ce81e","repo":"unslothai/unsloth","slug":"installer-timed-out-after-timeout-seconds-s","errorCode":null,"errorMessage":"installer timed out after {timeout_seconds}s","messagePattern":"installer timed out after (.+?)s","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/utils/prebuilt/update_flow.py","lineNumber":411,"sourceCode":"                    announced.add(child_pid)\n                else:\n                    forget_pid(child_pid)\n                    announced.discard(child_pid)\n                continue\n            m = PROGRESS_LINE_RE.search(line)\n            if m is None:\n                continue\n            set_progress(min(float(m.group(1)) / 100.0, 1.0) * DOWNLOAD_PROGRESS_CEILING)\n        returncode = proc.wait()\n    finally:\n        watchdog.cancel()\n        if proc.poll() is not None:\n            forget_pid(proc.pid)\n        # Anything it started and never reported as stopped, whether it timed\n        # out, exited nonzero, or died mid-line.\n        _stop_announced()\n    if timed_out.is_set():\n        raise RuntimeError(f\"installer timed out after {timeout_seconds}s\")\n    if returncode != 0:\n        tail = \"\".join(tail_lines).strip()[-1500:]\n        raise InstallerExit(returncode, f\"installer exited {returncode}: {tail or 'no output'}\")\n\n\ndef _new_phase_record(spec: dict) -> dict:\n    \"\"\"Initial breakdown entry for one phase of a chained job.\"\"\"\n    runnable = spec.get(\"run\") is not None\n    return {\n        \"state\": PHASE_PENDING if runnable else PHASE_SKIPPED,\n        \"reason\": None if runnable else spec.get(\"skip_reason\"),\n        \"progress\": None,\n        \"to_tag\": None,\n        \"reload_required\": None,\n        \"message\": \"\",\n        \"error\": None,\n    }\n","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/prebuilt/update_flow.py#L393-L429","documentation":"Raised by the prebuilt-installer update flow after a watchdog timer fires and the installer subprocess is terminated. The flow runs the installer with a progress watchdog; when timed_out is set by the time proc.wait() returns, the job aborts with this RuntimeError naming the configured timeout_seconds. It indicates the installer process hung (e.g. stalled download, blocked prompt), not merely that it was slow.","triggerScenarios":"Running the prebuilt update flow where the installer subprocess exceeds timeout_seconds without exiting — the watchdog cancels and kills it, the finally block stops anything it announced (_stop_announced()), and this error propagates. Typical with a hung network connection mid-download or an installer waiting on interactive input.","commonSituations":"Slow or stalled network during a large model/runtime download, installer blocked on a prompt in a non-TTY environment, antivirus or disk I/O stalling the process on Windows, or a timeout_seconds configured too low for the payload size.","solutions":["Check network connectivity/throughput to the installer download host and retry — transient stalls are the most common cause.","Inspect the captured tail_lines output logged just before the timeout to see where the installer stalled (progress percentage vs silent hang).","Increase timeout_seconds for the job if the artifact is legitimately large and the download is progressing (progress updates were advancing when killed).","On Windows, check whether antivirus/Defender is scanning the installer and exclude the studio install directory."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    run_installer(spec)\nexcept RuntimeError as e:\n    if 'installer timed out' in str(e):\n        log.warning('installer stalled; retrying once with fresh download')\n        run_installer(spec, timeout_seconds=timeout_seconds * 2)\n    else:\n        raise","preventionTips":["Size timeout_seconds to the artifact size and expected bandwidth, not a fixed guess.","Monitor the progress callback — steadily advancing progress that dies at the timeout means the ceiling is too low; frozen progress means a network stall worth investigating before retry.","Keep the target directory and network stable (no VPN switches, no disk-full) during updates."],"tags":["timeout","installer","subprocess","network","python"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}