{"record":{"id":"b8185c2e07f4a0c8","repo":"unslothai/unsloth","slug":"dataset-not-found-in-cache","errorCode":null,"errorMessage":"Dataset not found in cache","messagePattern":"Dataset not found in cache","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"studio/backend/hub/services/datasets/cache_inventory.py","lineNumber":665,"sourceCode":"    # ``scan_cache_dir()`` skips blob-only/corrupt repos the revision delete can't touch, yet the\n    # fallback scanner shows them, so purge the whole dir. Hub cache targets only.\n    cache_purged = partial_purged = state_purged = False\n    if target_root is not None:\n        cache_purged = purge_repo_cache_dirs(\"dataset\", repo_id, root = target_root)\n        partial_purged = purge_partial_repo(\"dataset\", repo_id, root = target_root)\n        state_purged = (\n            download_manifest.purge_all_state_for_repo(\"dataset\", repo_id, hub_cache = target_root)\n            > 0\n        )\n    if not (\n        deleted\n        or processed_deleted\n        or app_deleted\n        or cache_purged\n        or partial_purged\n        or state_purged\n    ):\n        raise HTTPException(status_code = 404, detail = \"Dataset not found in cache\")\n    return {\"status\": \"deleted\", \"repo_id\": repo_id}\n\n\ndef _delete_processed_dataset_cache(\n    repo_id: str, only_roots: Optional[set[Path]] = None\n) -> tuple[bool, list[str]]:\n    import shutil\n\n    target = repo_id.replace(\"/\", \"___\")\n    folded_target = target.lower()\n    deleted = False\n    failures: list[str] = []\n    for root in _hf_datasets_cache_roots():\n        # Scope to the selected cache's datasets root(s) so copies under other cache homes survive.\n        if only_roots is not None and root.resolve(strict = False) not in only_roots:\n            continue\n        try:\n            entries = [","sourceCodeStart":647,"sourceCodeEnd":683,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/hub/services/datasets/cache_inventory.py#L647-L683","documentation":"HTTP 404 raised when a delete-dataset-cache request completed without any location reporting that it actually deleted or purged something. All outcome flags (deleted, processed_deleted, app_deleted, cache_purged, partial_purged, state_purged) were false, meaning no cache location knew about this repo_id. It is the 'nothing to delete' sentinel, not a failure.","triggerScenarios":"Calling delete for a repo_id never downloaded, a repo_id whose case differs from the cached directory name (before case canonicalization), or re-sending a delete request that already succeeded.","commonSituations":"Frontend fires the delete twice (double-click or retry after a timeout); user typed the dataset name with different casing; the cache was cleared out-of-band while the UI still listed the dataset.","solutions":["Treat 404 on delete as idempotent success if the goal is 'make sure it is gone'.","Verify the exact repo_id string (including owner prefix and case) matches what the cache inventory endpoint reports.","List cache entries first (the cache inventory endpoint) to confirm the dataset is actually present before deleting.","If the UI still shows it, refresh the inventory — the listing likely came from a stale response."],"exampleFix":"// before\ndeleteDatasetCache(repoId); // throws on 404\n// after\ntry { await deleteDatasetCache(repoId); }\ncatch (e) { if (e.status !== 404) throw e; /* already gone */ }","handlingStrategy":"try-catch","validationCode":"resp = list_cache_inventory(client)\nknown = {e.repo_id for e in resp.entries}\nif repo_id not in known:\n    skip_delete()  # nothing to delete; avoids the 404 round trip","typeGuard":null,"tryCatchPattern":"try:\n    delete_dataset_cache(client, repo_id)\nexcept HTTPStatusError as e:\n    if e.response.status_code == 404:\n        pass  # already gone — treat as success (idempotent delete)\n    else:\n        raise","preventionTips":["Design delete flows to be idempotent and treat 404 as success.","Always pass the canonical repo_id returned by the inventory endpoint, preserving case.","Refresh the dataset list after any delete so the UI cannot re-send stale entries."],"tags":["cache","http-404","idempotency","delete"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}