{"record":{"id":"16c2331512128e39","repo":"unslothai/unsloth","slug":"folder-was-concurrently-removed","errorCode":null,"errorMessage":"Folder was concurrently removed","messagePattern":"Folder was concurrently removed","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"warning","filePath":"studio/backend/hub/storage/scan_folders.py","lineNumber":178,"sourceCode":"            return dict(existing), False\n        inserted = False\n        try:\n            conn.execute(\n                \"INSERT INTO scan_folders (path, created_at) VALUES (?, ?)\",\n                (normalized, now),\n            )\n            conn.commit()\n            inserted = True\n        except sqlite3.IntegrityError:\n            pass\n        fallback_sql = (\n            \"SELECT id, path, created_at FROM scan_folders WHERE path = ? COLLATE NOCASE\"\n            if is_win\n            else \"SELECT id, path, created_at FROM scan_folders WHERE path = ?\"\n        )\n        row = conn.execute(fallback_sql, (normalized,)).fetchone()\n        if row is None:\n            raise ValueError(\"Folder was concurrently removed\")\n        return dict(row), inserted\n    finally:\n        conn.close()\n\n\ndef add_scan_folder(path: str) -> dict:\n    \"\"\"Add a readable directory for the local OS user; not a multi-user sandbox.\"\"\"\n    row, _ = add_scan_folder_with_status(path)\n    return row\n\n\ndef remove_scan_folder(id: int) -> bool:\n    # sqlite INTEGER is signed 64-bit; ids outside that range cannot exist.\n    if not -(2**63) <= id < 2**63:\n        return False\n    conn = get_connection()\n    try:\n        _ensure_schema(conn)","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/hub/storage/scan_folders.py#L160-L196","documentation":"Raised when, after INSERT (or its IntegrityError on a duplicate) and commit, re-selecting the row by path returns None. The path column is UNIQUE, so the only way the row vanishes between commit and SELECT is another connection DELETEing it concurrently — studio uses per-call SQLite connections, so a remove_scan_folder racing an add_scan_folder_with_status for the same path triggers this. It signals a lost race, not corruption.","triggerScenarios":"Two API calls in flight simultaneously: POST /scan-folders {path} and DELETE /scan-folders {id} for the same path; the DELETE's commit lands between the add's commit and its re-select.","commonSituations":"UI allowing rapid add-then-remove clicks with in-flight requests; automation scripts adding and pruning folders; retry storms from a flaky client.","solutions":["Retry the add if the folder should exist — the race is timing-dependent and a retry will succeed when no delete is in flight.","Serialize add/remove calls for the same path client-side (disable the remove button until add settles).","Treat as informational if the intent was removal anyway: the folder ended up unregistered either way."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in range(2):\n    try:\n        row, inserted = add_scan_folder_with_status(path)\n        break\n    except ValueError as e:\n        if \"concurrently removed\" in str(e) and attempt == 0:\n            continue  # lost an add/remove race; safe to retry\n        raise","preventionTips":["Serialize add/remove requests per path in the client (disable the delete button until add settles).","Treat this error as benign if the desired end state was 'not registered'."],"tags":["race-condition","sqlite","scan-folders","concurrency"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}