{"record":{"id":"8437aac19b2bfa48","repo":"java-native-access/jna","slug":"move-to-trash-aborted","errorCode":null,"errorMessage":"Move to trash aborted","messagePattern":"Move to trash aborted","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"contrib/platform/src/com/sun/jna/platform/win32/W32FileUtils.java","lineNumber":55,"sourceCode":"\n    @Override\n    public void moveToTrash(File... files) throws IOException {\n        Shell32 shell = Shell32.INSTANCE;\n        ShellAPI.SHFILEOPSTRUCT fileop = new ShellAPI.SHFILEOPSTRUCT();\n        fileop.wFunc = ShellAPI.FO_DELETE;\n        String[] paths = new String[files.length];\n        for (int i=0;i < paths.length;i++) {\n            paths[i] = files[i].getAbsolutePath();\n        }\n        fileop.pFrom = fileop.encodePaths(paths);\n        fileop.fFlags = ShellAPI.FOF_ALLOWUNDO|ShellAPI.FOF_NO_UI;\n        int ret = shell.SHFileOperation(fileop);\n        if (ret != 0) {\n            throw new IOException(\"Move to trash failed: \" + fileop.pFrom + \": \" +\n                                  Kernel32Util.formatMessageFromLastErrorCode(ret));\n        }\n        if (fileop.fAnyOperationsAborted) {\n            throw new IOException(\"Move to trash aborted\");\n        }\n    }\n}\n","sourceCodeStart":37,"sourceCodeEnd":59,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/W32FileUtils.java#L37-L59","documentation":"After SHFileOperation returns success (ret == 0), moveToTrash checks the fAnyOperationsAborted flag of the SHFILEOPSTRUCT. If the user (or a FOF_NOUI-suppressed dialog policy) aborted the operation, an IOException 'Move to trash aborted' is thrown even though no error code was returned.","triggerScenarios":"SHFileOperation completes with code 0 but fileop.fAnyOperationsAborted is TRUE — the shell cancelled some or all operations, e.g. recycle-bin disabled/group policy forbids deletion confirmation bypass, or files vanished mid-operation.","commonSituations":"Corporate group policies disabling the Recycle Bin on the relevant drive; files deleted concurrently by another process while the operation ran; user-driven cancellation when UI is not fully suppressed.","solutions":["Catch this IOException and inform the user the recycle was cancelled, then decide whether to delete permanently instead","Verify the Recycle Bin is enabled for the drive and no group policy blocks recycling","Check file existence before the call and re-verify after, handling partial aborts","Treat 'aborted' as a soft failure — retry once or skip the file"],"exampleFix":"// before\nFileUtils.moveToTrash(files);\n// after\ntry {\n    FileUtils.moveToTrash(files);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"aborted\")) {\n        // fall back: skip or ask user before permanent delete\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Check Recycle Bin availability for the drive (best-effort)\nFile bin = new File(driveRoot, \"$Recycle.Bin\");\nboolean recycleEnabled = bin.exists();","typeGuard":null,"tryCatchPattern":"try {\n    FileUtils.moveToTrash(files);\n} catch (IOException e) {\n    if (\"Move to trash aborted\".equals(e.getMessage())) {\n        // treat as cancelled: skip or prompt user\n    }\n}","preventionTips":["Verify the Recycle Bin is enabled on target drives (group policy)","Treat 'aborted' as a soft/cancelled outcome, not corruption","Re-check file existence after the call to detect partial aborts"],"tags":["win32","recycle-bin","user-abort"],"backgroundTag":"operation-aborted","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}