Skip to content

Fix file.move failing on 2nd move when createParentDirectories=true and overwrite=true - #300

Open
GDLMadushanka wants to merge 1 commit into
wso2-extensions:masterfrom
GDLMadushanka:fix/issue-5082
Open

Fix file.move failing on 2nd move when createParentDirectories=true and overwrite=true#300
GDLMadushanka wants to merge 1 commit into
wso2-extensions:masterfrom
GDLMadushanka:fix/issue-5082

Conversation

@GDLMadushanka

@GDLMadushanka GDLMadushanka commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes wso2/product-integrator-mi#4934
The file.move operation fails with FileSystemException: Could not create folder "...abc.txt" because it already exists and is a file on every move after the first, when createParentDirectories=true and overwrite=true are both set.

Root Cause

MoveFiles.moveFile() (line 289) was calling createFolder() on the full destination file path instead of the destination's parent directory:

// BEFORE (buggy)
if (createNonExistingParents) {
    destinationFile.createFolder();   // called on the file path, not the parent
}
  • Run 1: /target/abc.txt does not exist → VFS creates it as a folder, then moveTo() overwrites it with the file. Works by accident.
  • Run 2: /target/abc.txt already exists as a regular file → VFS refuses to create a folder where a file already exists → FileSystemException. Because this exception is thrown before moveTo(), overwrite=true is silently ineffective.

Fix

Resolve destinationFile.getParent() and call createFolder() only when the parent is non-null and does not yet exist:

// AFTER (fixed)
if (createNonExistingParents) {
    FileObject parent = destinationFile.getParent();
    if (parent != null && !parent.exists()) {
        parent.createFolder();
    }
}

The !overWrite && destinationFile.exists() guard, the else/debug-log branch, and srcFile.moveTo(destinationFile) are unchanged. The moveFolder path is untouched.

Files Changed

File Change
src/main/java/org/wso2/carbon/connector/operations/MoveFiles.java Replace destinationFile.createFolder() with guarded parent-directory creation
src/test/java/org/wso2/carbon/connector/operations/MoveFilesParentDirectoryTest.java New: 5 unit tests for MoveFiles.moveFile() (see below)
src/test/resources/testng-unit.xml Register MoveFilesParentDirectoryTest in the unit suite

Tests Added

MoveFiles previously had zero automated tests. Added MoveFilesParentDirectoryTest (5 tests) using a real StandardFileSystemManager against a temp directory — no MI server or carbon zip required:

# Scenario What it verifies
1 createParentDirectories=true + overwrite=true, move TWICE (the reported regression) Second move succeeds, dest is a file with run-2 content, source removed
1b Same scenario with the old buggy createFolder-on-destination logic Run 2 throws "Could not create folder" — pins the exact bug
2 createParentDirectories=true into a missing target dir Parent created as a directory, file lands inside as a file
3 createParentDirectories=true + overwrite=false, dest present Returns false / FileAlreadyExistsException; dest untouched; no folder-creation exception
4 renameTo + createParentDirectories=true into missing dir Parent created; file moved to renamed destination inside it

Full unit suite result: Tests run: 15, Failures: 0, Skips: 1 (9 pre-existing WriteFileTempFileResolutionTest cases + 5 new cases; 1 skip is the pre-existing smb2 case).

Verification

Independently verified on a freshly extracted WSO2 MI 4.4.0 pack:

  • Built connector from fix/issue-5082 working tree (mvn clean package -DskipTests).
  • Deployed FILE_CONN (LOCAL, workingDir=/tmp/file5082) + MoveTestAPI (overwrite=true) + MoveNoOverwriteAPI (overwrite=false).
  • Run 1: HTTP 200 {"success":true} — file moved, /target created as directory, file inside it.
  • Run 2 (the regression): HTTP 200 {"success":true} — destination overwritten, source removed. Zero "Could not create folder" errors in the full server log.
  • Parent-dir re-creation check: HTTP 200 — /target recreated, file inside.
  • Negative (overwrite=false): correct FileAlreadyExistsException; destination untouched; no folder-creation exception.
  • 3 consecutive overwrite moves: all HTTP 200.

grep -c "Could not create folder" across the entire verify session = 0.

…nd overwrite=true

MoveFiles.moveFile() was calling createFolder() on the destination FILE path instead of
the destination's parent directory. On the first move this worked by accident (VFS created
the path as a folder and moveTo() overwrote it); on the second move the destination already
existed as a regular file, so VFS threw "Could not create folder ... because it already exists
and is a file" at MoveFiles.java:289 — before moveTo() was ever reached, making overwrite=true
silently ineffective.

Fix: resolve destinationFile.getParent() and call createFolder() only when the parent is
non-null and does not yet exist. The !overWrite && exists() guard and moveTo() call are
unchanged; the folder-move path (moveFolder) is untouched.

Adds MoveFilesParentDirectoryTest (5 new unit tests) covering the regression, parent-dir
creation, overwrite=false negative path, and renameTo + createParentDirectories. Full unit
suite: 15 run, 0 failures, 1 skip (pre-existing smb2 case).

Fixes: wso2/product-integrator-mi#4934
Patch: wso2-enterprise/wso2-integration-internal#5082
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant