unslothai/unsloth · error · RuntimeError

No export subprocess running

Error message

No export subprocess running

What it means

Raised by ExportOrchestrator._send_cmd when a command is sent but the multiprocessing Queue to the export worker was never created (self._cmd_queue is None). It means no export subprocess was started — or it was already shut down — before an operation tried to talk to it. This is a lifecycle/sequencing error, not a subprocess failure.

Source

Thrown at studio/backend/core/export/orchestrator.py:330

        logger.info("Export subprocess shut down")
        return True

    def _cleanup(self):
        """atexit handler."""
        self._shutdown_subprocess(timeout = 5.0)

    def _ensure_subprocess_alive(self) -> bool:
        """Check if subprocess is alive."""
        return self._proc is not None and self._proc.is_alive()

    # ------------------------------------------------------------------
    # Queue helpers
    # ------------------------------------------------------------------

    def _send_cmd(self, cmd: dict) -> None:
        """Send a command to the subprocess."""
        if self._cmd_queue is None:
            raise RuntimeError("No export subprocess running")
        try:
            self._cmd_queue.put(cmd)
        except (OSError, ValueError) as exc:
            raise RuntimeError(f"Failed to send command to subprocess: {exc}")

    def _read_resp(self, timeout: float = 1.0) -> Optional[dict]:
        """Read a response from the subprocess (non-blocking with timeout)."""
        if self._resp_queue is None:
            return None
        try:
            return self._resp_queue.get(timeout = timeout)
        except queue.Empty:
            return None
        except (EOFError, OSError, ValueError):
            return None

    def _wait_response(
        self,

View on GitHub (pinned to 203007d190)

Solutions

  1. Ensure load_checkpoint() (which spawns the subprocess and creates _cmd_queue) has completed successfully before issuing any export command
  2. Guard every command-sending call site with _ensure_subprocess_alive() and re-load the checkpoint when it returns False
  3. Check the orchestrator state (e.g. is_export_active / worker-alive flags) at the route level and return a 409-style 'load a checkpoint first' response instead of letting the RuntimeError escape
  4. If this happens after a crash, inspect the backend log for the earlier 'Export subprocess crashed' / shutdown event that cleared the queue

Example fix

// before
orchestrator.run_export('gguf', params)

// after
if not orchestrator._ensure_subprocess_alive():
    ok, msg = orchestrator.load_checkpoint(...)
    if not ok:
        raise RuntimeError(msg)
orchestrator.run_export('gguf', params)
Defensive patterns

Strategy: validation

Validate before calling

def can_send_export_cmd(orch) -> bool:
    return orch._cmd_queue is not None and orch._ensure_subprocess_alive()

Try / catch

try:
    orch.run_export(...)
except RuntimeError as e:
    if str(e) == "No export subprocess running":
        ok, msg = orch.load_checkpoint(last_load_params)
        # retry once after successful load
    raise

Prevention

When it happens

Trigger: Calling run_export() or any path that calls _send_cmd() before load_checkpoint()/start has spawned the worker; calling _send_cmd() after _shutdown_subprocess() or after a crash path that cleared _cmd_queue; sending a second command after a failed checkpoint load that tore the subprocess down.

Common situations: API/route calls export before load; retry logic re-enters export after a previous export's cleanup ran; startup race where the client issues export immediately while the backend still initializing; worker teardown running concurrently with a queued op.

Related errors


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