{"record":{"id":"4f3ca06bffb5b084","repo":"invoke-ai/InvokeAI","slug":"invalid-staged-delete-token","errorCode":null,"errorMessage":"Invalid staged-delete token","messagePattern":"Invalid staged-delete token","errorType":"exception","errorClass":"ImageFileDeleteException","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/image_files/image_files_disk.py","lineNumber":234,"sourceCode":"            for index, source in enumerate(candidates):\n                with self.__cache_lock:\n                    self.__cache.pop(source, None)\n                if source.exists():\n                    destination = staging_dir / str(index)\n                    source.replace(destination)\n                    staged.append((source, destination))\n            return _StagedDelete(directory=staging_dir, files=staged)\n        except Exception as e:\n            for source, destination in reversed(staged):\n                if destination.exists():\n                    source.parent.mkdir(parents=True, exist_ok=True)\n                    destination.replace(source)\n            shutil.rmtree(staging_dir, ignore_errors=True)\n            raise ImageFileDeleteException from e\n\n    def commit_delete(self, token: object) -> None:\n        if not isinstance(token, _StagedDelete):\n            raise ImageFileDeleteException(\"Invalid staged-delete token\")\n        try:\n            shutil.rmtree(token.directory)\n        except Exception as e:\n            raise ImageFileDeleteException from e\n\n    def rollback_delete(self, token: object) -> None:\n        if not isinstance(token, _StagedDelete):\n            raise ImageFileDeleteException(\"Invalid staged-delete token\")\n        try:\n            for source, destination in reversed(token.files):\n                if destination.exists():\n                    source.parent.mkdir(parents=True, exist_ok=True)\n                    destination.replace(source)\n            shutil.rmtree(token.directory, ignore_errors=True)\n        except Exception as e:\n            raise ImageFileDeleteException from e\n\n    def get_path(self, image_name: str, thumbnail: bool = False, image_subfolder: str = \"\") -> Path:","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/image_files/image_files_disk.py#L216-L252","documentation":"commit_delete() validates that the token passed to it is an internal _StagedDelete instance returned by stage_delete(). Passing anything else — None, a string, or a token from a different service instance/version — raises this ImageFileDeleteException with the message \"Invalid staged-delete token\". It is a programming/contract error, not an I/O failure.","triggerScenarios":"Calling commit_delete(token) with a value not produced by stage_delete() on the same service: None, a mock, a deserialized/foreign object, or a hand-built token.","commonSituations":"Persisting the token to storage and passing back the wrong type; passing a token from an older InvokeAI version after upgrade; typos where a path string is passed instead of the token; test code fabricating tokens.","solutions":["Pass the exact object returned by stage_delete() to commit_delete() in the same process","Do not serialize/persist the token — treat it as an opaque in-memory handle","Complete the delete lifecycle immediately after staging (stage → commit or rollback) within one session","If the token was lost, locate the staging directory and restore files manually, then call rollback-free cleanup"],"exampleFix":"// before\ntoken = services.images.stage_delete(name)\n# ... later, possibly different object\nservices.images.commit_delete(name)  # Invalid staged-delete token\n// after\ntoken = services.images.stage_delete(name)\nservices.images.commit_delete(token)","handlingStrategy":"type-guard","validationCode":"token = services.images.stage_delete(image_name)\nassert token is not None","typeGuard":"from invokeai.app.services.image_files.image_files_disk import _StagedDelete\ndef is_valid_token(token: object) -> bool:\n    return isinstance(token, _StagedDelete)","tryCatchPattern":"try:\n    services.images.commit_delete(token)\nexcept ImageFileDeleteException as e:\n    if \"Invalid staged-delete token\" in str(e):\n        raise TypeError(\"commit_delete requires the _StagedDelete from stage_delete()\") from e\n    raise","preventionTips":["Pass the exact object returned by stage_delete() — never a name, path, or serialized copy","Complete stage → commit/rollback within the same process/session","Type-hint the token variable as _StagedDelete to catch misuse statically"],"tags":["type-error","api-misuse","image-files","two-phase-delete"],"backgroundTag":"invalid-argument-type","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}