unslothai/unsloth · error · HTTPException
Could not update '{folder.name}' with the imported example (
Error message
Could not update '{folder.name}' with the imported example ({getattr(e, 'strerror', None) or e}). Nothing was written; try again. What it means
HTTP 409 from the import route's atomic promotion phase: after a successful materialization into staging, folding the old folder's files and os.replace(staging -> folder) failed with OSError/shutil.Error. Causes include an unmovable entry (permissions, file held open, Windows antivirus holding the rename), or a file appearing in the folder mid-move. The handler runs restore_folded() to put pre-existing entries back, then reports 'Nothing was written; try again' — the dataset folder is restored to its pre-import state.
Source
Thrown at studio/backend/routes/training.py:4294
if imported == 0:
raise HTTPException(
status_code = 502,
detail = f"No images found in '{entry['repo']}'.",
)
# Promote the fully-materialized staging dir as a UNIT: a same-filesystem rename is atomic, so a hard process death
# leaves either the old folder or the finished import. rmdir needs an empty target, so fold any pre-existing files (a .thumbs cache, an older metadata.jsonl) INTO staging first and keep one atomic promotion.
try:
for p in sorted(folder.iterdir()):
# Same name in both: the imported file wins, as the previous per-file move did. Park the old one in the rescue dir so the folder can be emptied for the rename without destroying it.
dest = (rescue if (staging / p.name).exists() else staging) / p.name
shutil.move(str(p), str(dest))
folded.append((dest, p))
os.rmdir(folder)
os.replace(str(staging), str(folder))
except (OSError, shutil.Error) as e:
# Every step here can fail (an unmovable entry, a folder that gained a file, a rename held by antivirus), and by then the folder's entries live only in the staging/rescue dirs the finally deletes.
restore_folded()
raise HTTPException(
status_code = 409,
detail = (
f"Could not update '{folder.name}' with the imported example "
f"({getattr(e, 'strerror', None) or e}). Nothing was written; try again."
),
)
finally:
shutil.rmtree(staging, ignore_errors = True)
shutil.rmtree(rescue, ignore_errors = True)
return _import_response(entry, folder, imported = imported)
return await asyncio.to_thread(do_import)
View on GitHub (pinned to 203007d190)
Solutions
- Simply retry the import — the message says nothing was written, and the restore path keeps the folder consistent; transient locks (AV scan finishing) clear on their own.
- Close other Studio tabs / labeling sessions using that dataset, then retry.
- Fix permissions on the datasets root and ensure it is on a local filesystem; add AV exclusions for the datasets directory.
- If it keeps failing on Windows, exclude the Studio datasets folder from real-time antivirus scanning.
Example fix
# ensure writable, local, and not contended chmod -R u+w /studio/datasets/myset lsof +D /studio/datasets/myset # find holders on POSIX
Defensive patterns
Strategy: retry
Validate before calling
import os
from pathlib import Path
def folder_promotable(folder: Path) -> bool:
try:
probe = folder / '.promote-probe'
probe.write_text('')
probe.unlink()
return os.access(folder, os.W_OK | os.X_OK)
except OSError:
return False Type guard
def is_promotion_failure(exc: HTTPException) -> bool:
return exc.status_code == 409 and 'Could not update' in str(exc.detail) Try / catch
for attempt in range(3):
try:
resp = await api.importExample(ex.id)
break
except HTTPStatusError as e:
if e.response.status_code == 409 and 'Could not update' in e.response.text:
await backoff(attempt) # AV/lock often clears; folder was restored intact
continue
raise Prevention
- Retry 409 'Could not update' after a short delay — the restore path leaves the folder consistent, so retry is safe.
- Keep datasets on a local filesystem; avoid NFS/SMB for the datasets root.
- Add AV exclusions for the datasets directory on Windows.
- Do not edit a dataset (captions, thumbnails) while an example import into it is running.
When it happens
Trigger: The import succeeded in fetching everything, then: a permissions error moving a .thumbs cache file, an OS-level rename failure (Windows file lock by antivirus/indexer/another process), or a concurrent writer adding a file to the folder between the emptiness check and the promotion.
Common situations: Windows AV scanning newly written staging files during promotion; network filesystems (NFS/SMB) where rename over an existing dir is not atomic or fails; another session writing captions/thumbnails into the folder during the import; restrictive permissions on the datasets root.
Related errors
- An import into '{folder.name}' is already running. Wait for
- Execution artifacts are no longer available.
- Execution artifact path is not a dataset folder.
- GGUF conversion produced a symlink, refusing to relocate it:
- Local base_repo is not a diffusers pipeline directory (no {i
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/609fc753985f876a.
Report an issue: GitHub.