unslothai/unsloth · warning · HTTPException

An import into '{folder.name}' is already running. Wait for

Error message

An import into '{folder.name}' is already running. Wait for it to finish, then reload the dataset list.

What it means

HTTP 409 from the example-dataset import route: a per-folder import lock (_dataset_import_lock(folder), acquired non-blocking) is already held, meaning another import into the same dataset name is in flight. Exists because the training interlock counts mutations rather than excluding concurrent ones — two imports into the same empty name would otherwise both pass the emptiness check and merge.

Source

Thrown at studio/backend/routes/training.py:4222

    """Materialize a curated example dataset into a Studio dataset folder (images + .txt
    captions), ready to train. Idempotent: a folder that already holds images is returned
    as-is rather than re-downloaded."""
    _require_diffusion_dataset_mutable()
    entry = _example_by_id(body.id)
    folder = _resolve_dataset_folder(body.name or entry["id"], must_exist = False)

    def do_import() -> DiffusionDatasetImportResponse:
        folder.mkdir(parents = True, exist_ok = True)
        # Any trainable item already in the folder makes this a no-op: dropping example images
        # into a folder the user filled with clips would silently mix two dataset kinds.
        summary = _diffusion_dataset_summary(folder)
        if summary.image_count > 0 or summary.clip_count > 0:
            return _import_response(entry, folder, imported = 0)
        # One import at a time per dataset folder: the training interlock COUNTS mutations rather than excluding them, so two
        # imports into the same empty name both passed the emptiness check and merged. Refusing the second is honest.
        lock = _dataset_import_lock(folder)
        if not lock.acquire(blocking = False):
            raise HTTPException(
                status_code = 409,
                detail = (
                    f"An import into '{folder.name}' is already running. Wait for it to finish, "
                    "then reload the dataset list."
                ),
            )
        try:
            return _do_import_locked(entry, folder)
        finally:
            lock.release()

    def _do_import_locked(entry: dict, folder: Path) -> DiffusionDatasetImportResponse:
        import os
        import shutil
        import tempfile

        imported = 0
        # Re-read under the lock: a winner may have promoted its staging dir while this request was checking, so returning the folder as-is matches the idempotent path.

View on GitHub (pinned to 203007d190)

Solutions

  1. Wait for the in-flight import to finish, then reload the dataset list — the running import's result will be there.
  2. Prevent double-submits: disable the import button while a request is in flight.
  3. If the first import crashed and the lock is stale, verify no import thread is alive, then restart the backend process to clear in-memory locks.

Example fix

// before
button.onclick = () => api.importExample(ex.id);
// after
button.disabled = true;
try { await api.importExample(ex.id); } finally { button.disabled = false; }
Defensive patterns

Strategy: retry

Validate before calling

async function importOnce(exId) {
  if (inFlight[exId]) return inFlight[exId];
  inFlight[exId] = api.importExample(exId).finally(() => delete inFlight[exId]);
  return inFlight[exId];
}

Type guard

def is_import_in_flight(exc: HTTPException) -> bool:
    return exc.status_code == 409 and 'already running' in str(exc.detail)

Try / catch

try:
    resp = await api.importExample(ex.id)
except HTTPStatusError as e:
    if e.response.status_code == 409 and 'already running' in e.response.text:
        await wait_for_import_completion(ex)  # poll dataset list, then proceed
        return
    raise

Prevention

When it happens

Trigger: Two concurrent POSTs to import an example into the same dataset name (double-click of an import button, script retry while the first request is still running). The second request 409s immediately at lock.acquire(blocking=False).

Common situations: UI double-submit without disabling the button; impatient retries of a slow import (HF downloads take minutes); parallel automation scripts importing the same example.

Related errors


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