{"record":{"id":"badea38a9a779585","repo":"Comfy-Org/ComfyUI","slug":"cannot-mark-missing-assets-while-scan-is-running","errorCode":null,"errorMessage":"Cannot mark missing assets while scan is running","messagePattern":"Cannot mark missing assets while scan is running","errorType":"exception","errorClass":"ScanInProgressError","httpStatus":409,"severity":"warning","filePath":"app/assets/seeder.py","lineNumber":404,"sourceCode":"        This is a non-destructive soft-delete operation. Assets and their\n        metadata are preserved, but references are flagged as missing.\n        They can be restored if the file reappears in a future scan.\n\n        This operation is decoupled from scanning to prevent partial scans\n        from accidentally marking assets belonging to other roots.\n\n        Should be called explicitly when cleanup is desired, typically after\n        a full scan of all roots or during maintenance.\n\n        Returns:\n            Number of references marked as missing\n\n        Raises:\n            ScanInProgressError: If a scan is currently running\n        \"\"\"\n        with self._lock:\n            if self._state != State.IDLE:\n                raise ScanInProgressError(\n                    \"Cannot mark missing assets while scan is running\"\n                )\n            self._state = State.RUNNING\n\n        try:\n            if not dependencies_available():\n                logging.warning(\n                    \"Database dependencies not available, skipping mark missing\"\n                )\n                return 0\n\n            all_prefixes = get_all_known_prefixes()\n            marked = mark_missing_outside_prefixes_safely(all_prefixes)\n            if marked > 0:\n                logging.info(\"Marked %d references as missing\", marked)\n            return marked\n        finally:\n            with self._lock:","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/app/assets/seeder.py#L386-L422","documentation":"ScanInProgressError raised by the seeder's mark-missing routine when its state machine is not IDLE at call time. The routine needs exclusive access to flip state to RUNNING and sweep for references whose files disappeared, so it refuses to start concurrently with a scan. Note the routine sets RUNNING itself and later restores IDLE; dependencies being unavailable skips the work but still returns 0.","triggerScenarios":"Invoking mark_missing (or the maintenance endpoint wrapping it) while a library scan is in progress — including when the previous mark-missing run has not yet returned to IDLE.","commonSituations":"Scheduling maintenance (cron/CI) without accounting for long library scans on huge roots; a crashed scan leaving the state stuck at RUNNING; UI buttons for 'clean up missing files' enabled while a scan badge is active.","solutions":["Wait for the current scan to finish (poll state until IDLE) before calling mark-missing.","Disable/gate the mark-missing action in the UI whenever a scan is active.","If the state is stuck at RUNNING after a crash, restart the seeder/process to reset the state machine.","Catch ScanInProgressError and surface a 'scan in progress, try again later' message instead of retrying immediately."],"exampleFix":"// before\nseeder.mark_missing()\n\n// after\nfrom app.assets.seeder import ScanInProgressError\ntry:\n    seeder.mark_missing()\nexcept ScanInProgressError:\n    return {\"status\": \"busy\", \"detail\": \"scan running; retry after it completes\"}","handlingStrategy":"retry","validationCode":"def can_mark_missing(seeder) -> bool:\n    # state must be IDLE; expose or read the seeder's state if available\n    return seeder._state.name == \"IDLE\" if hasattr(seeder, \"_state\") else True","typeGuard":null,"tryCatchPattern":"from app.assets.seeder import ScanInProgressError\ntry:\n    removed = seeder.mark_missing()\nexcept ScanInProgressError:\n    # schedule a retry after the scan completes; do not spin\n    return {\"status\": \"busy\", \"retry_after\": \"scan completes\"}","preventionTips":["Gate mark-missing UI actions on the seeder reporting IDLE.","Schedule maintenance windows that cannot overlap scan windows.","Treat a stuck RUNNING state after a crash as a bug — restart to reset the state machine."],"tags":["concurrency","state-machine","scan","maintenance"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}