Skip to content

Moving non-empty directory via drag and drop to linked folder is broken #2819

Description

@iloveeclipse
  1. Create simple (non Java) project, which has linked folder linked pointing to "outside" directory.
  2. Create directory hello in the project and add empty text.txt file to it.
  3. In Project Explorer or Package Explorer, select the hello directory created before and move this directory via "drag and drop" to the linked folder.
  4. Kaboom (below error and stack from Package Explorer, because Project Explorer currently doesn't log anything but also fails with SWTException):
Image 5) Problem (beside error): the target directory & files are created, but the original directory and files are still there and not deleted.
eclipse.buildId=4.41.0.I20260719-2300
java.version=25
java.vendor=Eclipse Adoptium
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US
Command-line arguments:  -os linux -ws gtk -arch x86_64 -data /data/4x_platform_workspace

org.eclipse.core.filesystem
Error
Mon Jul 20 17:14:24 CEST 2026
Problems encountered while deleting files.

java.util.concurrent.ExecutionException: org.eclipse.swt.SWTException: Unspecified error
	at java.base/java.util.concurrent.ForkJoinTask.getException(ForkJoinTask.java:568)
	at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:577)
	at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1019)
	at org.eclipse.core.internal.filesystem.local.LocalFile.internalDelete(LocalFile.java:349)
	at org.eclipse.core.internal.filesystem.local.LocalFile.delete(LocalFile.java:207)
	at org.eclipse.core.filesystem.provider.FileStore.move(FileStore.java:368)
	at org.eclipse.core.internal.filesystem.local.LocalFile.move(LocalFile.java:509)
	at org.eclipse.core.internal.localstore.FileSystemResourceManager.move(FileSystemResourceManager.java:923)
	at org.eclipse.core.internal.resources.ResourceTree.standardMoveFolder(ResourceTree.java:1038)
	at org.eclipse.core.internal.resources.Resource.unprotectedMove(Resource.java:1959)
	at org.eclipse.core.internal.resources.Resource.move(Resource.java:1621)
	at org.eclipse.ltk.core.refactoring.resource.MoveResourceChange.perform(MoveResourceChange.java:113)
	at org.eclipse.ltk.core.refactoring.CompositeChange.perform(CompositeChange.java:279)
	at org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange.access$0(DynamicValidationStateChange.java:1)
	at org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange.lambda$0(DynamicValidationStateChange.java:105)
	at org.eclipse.jdt.internal.core.BatchOperation.executeOperation(BatchOperation.java:41)
	at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:751)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2505)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2533)
	at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:6173)
	at org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange.perform(DynamicValidationStateChange.java:106)
	at org.eclipse.jdt.internal.corext.refactoring.reorg.JavaMoveProcessor$1.perform(JavaMoveProcessor.java:187)
	at org.eclipse.ltk.core.refactoring.CompositeChange.perform(CompositeChange.java:279)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.lambda$0(PerformChangeOperation.java:250)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2505)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2533)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.executeChange(PerformChangeOperation.java:289)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:214)
	at org.eclipse.jdt.internal.ui.refactoring.RefactoringExecutionHelper$Operation.run(RefactoringExecutionHelper.java:106)
	at org.eclipse.jdt.internal.core.BatchOperation.executeOperation(BatchOperation.java:41)
	at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:751)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2505)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2533)
	at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:6173)
	at org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:108)
	at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:421)
	at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:344)
	at org.eclipse.ui.internal.WorkbenchWindow.lambda$7(WorkbenchWindow.java:2343)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:69)
	at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2340)
	at org.eclipse.jdt.internal.ui.refactoring.RefactoringExecutionHelper.perform(RefactoringExecutionHelper.java:187)
	at org.eclipse.jdt.internal.ui.refactoring.RefactoringExecutionHelper.perform(RefactoringExecutionHelper.java:151)
	at org.eclipse.jdt.internal.ui.refactoring.reorg.ReorgMoveStarter.run(ReorgMoveStarter.java:73)
	at org.eclipse.jdt.internal.ui.packageview.SelectionTransferDropAdapter.handleDropMove(SelectionTransferDropAdapter.java:268)
	at org.eclipse.jdt.internal.ui.packageview.SelectionTransferDropAdapter.performDrop(SelectionTransferDropAdapter.java:205)
	at org.eclipse.jdt.internal.ui.dnd.JdtViewerDropAdapter.drop(JdtViewerDropAdapter.java:251)
	at org.eclipse.jface.util.DelegatingDropAdapter$3.run(DelegatingDropAdapter.java:227)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:47)
	at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:169)
	at org.eclipse.jface.util.DelegatingDropAdapter.drop(DelegatingDropAdapter.java:224)
	at org.eclipse.swt.dnd.DNDListener.handleEvent(DNDListener.java:104)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5878)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1659)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1685)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1668)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1382)
	at org.eclipse.swt.dnd.DropTarget.drag_data_received(DropTarget.java:447)
	at org.eclipse.swt.dnd.DropTarget.Drag_Data_Received(DropTarget.java:288)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_drag_get_data(Native Method)
	at org.eclipse.swt.dnd.DropTarget.drag_drop(DropTarget.java:492)
	at org.eclipse.swt.dnd.DropTarget.Drag_Drop(DropTarget.java:295)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_do_event(Native Method)
	at org.eclipse.swt.widgets.Display.eventProc(Display.java:1621)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_iteration_do(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4522)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1160)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1051)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:680)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:193)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:615)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:563)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1415)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1387)
Caused by: org.eclipse.swt.SWTException: Unspecified error
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
	at java.base/java.util.concurrent.ForkJoinTask.getException(ForkJoinTask.java:561)
	... 85 more

Trivial exampe project file on Linux for testing:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>A</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
	</natures>
	<linkedResources>
		<link>
			<name>linked</name>
			<type>2</type>
			<location>/tmp/linked</location>
		</link>
	</linkedResources>
</projectDescription>

This is regression from 6d514be / #1569.

The problem is, that the code which (finally) calls the org.eclipse.core.internal.filesystem.local.LocalFile.delete(int, IProgressMonitor) was supplying IProgressMonitor implementation which was supposed to be used on UI thread only, and the "DND" code is also executed on UI thread in both cases (if called from Package or Project explorers). The change in 6d514be however lets the code to be executed in non-UI threads, where supplied monitors fail while updating their UI widgets during monitor operations.

I've tried to play with both UI call sites and change the current implementation, but there are different paths where a progress monitor could be supplied and no single place where we know what is the "right" monitor to use in the current context.

I have a patch that would fix regression directly where it was introduced at org.eclipse.core.internal.filesystem.local.LocalFile.internalDelete(File, InfiniteProgress, ExecutorService).

Another clean solution would be to revert the patch, however I don't know yet how severe will be impact on performance, there was no data reported in #1461 or on #1569.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingregressionRegression defect

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions