jamiepine/voicebox · warning · HTTPException

Destination cannot be inside the current cache directory

Error message

Destination cannot be inside the current cache directory

What it means

400 from POST /models/migrate. Using Path.is_relative_to, the route rejects a destination whose resolved path is nested inside the resolved source. Moving the cache into itself would create recursive copies or move the directory into a child that gets moved along with it, corrupting the cache layout. Checked after the same-directory guard.

Source

Thrown at backend/routes/models.py:136

    return {"path": str(Path(hf_constants.HF_HUB_CACHE))}


@router.post("/models/migrate")
async def migrate_models(request: models.ModelMigrateRequest):
    """Move all downloaded models to a new directory with byte-level progress via SSE."""
    from huggingface_hub import constants as hf_constants

    source = Path(hf_constants.HF_HUB_CACHE)
    destination = Path(request.destination)

    if not source.exists():
        raise HTTPException(status_code=404, detail="Current model cache directory not found")

    if source.resolve() == destination.resolve():
        raise HTTPException(status_code=400, detail="Source and destination are the same directory")

    if destination.resolve().is_relative_to(source.resolve()):
        raise HTTPException(status_code=400, detail="Destination cannot be inside the current cache directory")

    progress_manager = get_progress_manager()
    model_dirs = [d for d in source.iterdir() if d.name.startswith("models--") and d.is_dir()]
    if not model_dirs:
        progress_manager.update_progress("migration", 1, 1, status="complete")
        progress_manager.mark_complete("migration")
        return {"moved": 0, "errors": [], "source": str(source), "destination": str(destination)}

    destination.mkdir(parents=True, exist_ok=True)

    same_fs = False
    try:
        same_fs = source.stat().st_dev == destination.stat().st_dev
    except OSError:
        pass

    async def migrate_background():
        moved = 0

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Pick a destination that is a sibling or on a different volume, not a child of the cache.
  2. GET /models/cache-dir and confirm your destination is not under that path (after resolving symlinks).
  3. If you need a backup, copy the cache elsewhere first, then point migrate at the external copy.
  4. Clean up any stray subdirectories created by a prior failed migration attempt before retrying.

Example fix

# before — destination inside cache
curl -X POST http://localhost:8000/models/migrate -d '{"destination":"/Users/me/.cache/huggingface/archive"}'
# after
curl -X POST http://localhost:8000/models/migrate -d '{"destination":"/Volumes/External/hf-cache"}'
Defensive patterns

Strategy: validation

Validate before calling

import { resolve, relative, isAbsolute } from 'path';
async function migrateTo(dest: string) {
  const { path: cacheDir } = await (await fetch('/models/cache-dir')).json();
  const rel = relative(resolve(cacheDir), resolve(dest));
  if (isAbsolute(rel) || (!rel.startsWith('..') && rel !== '')) {
    throw new Error('Destination is inside the cache directory');
  }
  return await fetch('/models/migrate', {method:'POST', body: JSON.stringify({destination: dest})});
}

Try / catch

try {
  await fetch('/models/migrate', {method:'POST', body: JSON.stringify({destination})});
} catch (e) {
  if (e.response?.status === 400 && /inside the current cache/i.test(e.response.detail)) {
    // suggest a sibling or external volume
  } else throw e;
}

Prevention

When it happens

Trigger: POST /models/migrate with destination like '/current/cache/subdir' or '/current/cache/.backup' — anything where destination.resolve() lives under source.resolve(). Also triggers when destination is a symlink whose target is inside the cache.

Common situations: User tries to 'make a backup folder inside the cache'; UI suggests a default destination nested under the cache root; migration retry pointing at a partially-created subdir from a prior failed run; symlink inside cache pointing deeper inside.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/1de9e5eae54bd254. Report an issue: GitHub.