java-native-access/jna · error · IOException

ret

ret

Error message

Move to trash failed: <pFrom>: <message>

What it means

W32FileUtils.moveToTrash uses the Win32 SHFileOperation with FOFF_ALLOWUNDO|FOF_NO_UI to send files to the Recycle Bin. If SHFileOperation returns a non-zero code, an IOException with the source path list and the formatted error message is thrown; the operation did not complete.

Solutions

  1. Ensure all paths passed are absolute and canonical (File.getCanonicalFile().getAbsolutePath())
  2. Exclude untrashable targets (drive roots, system files) before calling moveToTrash
  3. Decode the Win32 code in the message and handle it (e.g. unlock file, elevate permissions)
  4. Fall back to permanent delete (or skip) when recycling is impossible

Example fix

// before
FileUtils.moveToTrash(new File("relative/path.txt"));
// after
File f = new File("relative/path.txt").getCanonicalFile();
if (!f.getParent().equals(FileSystemView.getFileSystemView()...)) {
    FileUtils.moveToTrash(f);
}
Defensive patterns

Strategy: try-catch

Validate before calling

for (File f : files) {
    File c = f.getCanonicalFile();
    if (!c.isAbsolute() || c.getParent() == null) {
        throw new IllegalArgumentException("Not trashable: " + f);
    }
}

Try / catch

try {
    FileUtils.moveToTrash(files);
} catch (IOException e) {
    // parse error code; decide to skip, retry, or permanent delete
}

Prevention

When it happens

Trigger: SHFileOperation returns an error code such as DE_INVALIDFILES (invalid/relative path), DE_ROOTDIR (attempting to trash a drive root), DE_FLDDESTEXISTS, or access-denied style codes; passing paths that are not fully absolute canonical paths.

Common situations: Trying to move a drive root or special/system files to trash; files locked by another process; paths containing wildcards or non-canonical forms; permission issues on the containing directory.

Related errors


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

Appendix: source

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

    @Override
    public boolean hasTrash() {
        return true;
    }

    @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)