java-native-access/jna · warning · IOException

Move to trash aborted

Error message

Move to trash aborted

What it means

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.

Solutions

  1. Catch this IOException and inform the user the recycle was cancelled, then decide whether to delete permanently instead
  2. Verify the Recycle Bin is enabled for the drive and no group policy blocks recycling
  3. Check file existence before the call and re-verify after, handling partial aborts
  4. Treat 'aborted' as a soft failure — retry once or skip the file

Example fix

// before
FileUtils.moveToTrash(files);
// after
try {
    FileUtils.moveToTrash(files);
} catch (IOException e) {
    if (e.getMessage().contains("aborted")) {
        // fall back: skip or ask user before permanent delete
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Check Recycle Bin availability for the drive (best-effort)
File bin = new File(driveRoot, "$Recycle.Bin");
boolean recycleEnabled = bin.exists();

Try / catch

try {
    FileUtils.moveToTrash(files);
} catch (IOException e) {
    if ("Move to trash aborted".equals(e.getMessage())) {
        // treat as cancelled: skip or prompt user
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/8437aac19b2bfa48. Report an issue: GitHub.

Appendix: source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/W32FileUtils.java:55

    @Override
    public void moveToTrash(File... files) throws IOException {
        Shell32 shell = Shell32.INSTANCE;
        ShellAPI.SHFILEOPSTRUCT fileop = new ShellAPI.SHFILEOPSTRUCT();
        fileop.wFunc = ShellAPI.FO_DELETE;
        String[] paths = new String[files.length];
        for (int i=0;i < paths.length;i++) {
            paths[i] = files[i].getAbsolutePath();
        }
        fileop.pFrom = fileop.encodePaths(paths);
        fileop.fFlags = ShellAPI.FOF_ALLOWUNDO|ShellAPI.FOF_NO_UI;
        int ret = shell.SHFileOperation(fileop);
        if (ret != 0) {
            throw new IOException("Move to trash failed: " + fileop.pFrom + ": " +
                                  Kernel32Util.formatMessageFromLastErrorCode(ret));
        }
        if (fileop.fAnyOperationsAborted) {
            throw new IOException("Move to trash aborted");
        }
    }
}

View on GitHub (pinned to d036ad9781)