Skip to content

[🐛 Bug]: downloading a file from selenium grid was working with 4.38.0 is now broken with 4.39.0 #16738

@MohabMohie

Description

@MohabMohie

Description

Issue description

This code snippet is working fine with 4.38.0 and is now not working with 4.39.0

var downloadManager = (HasDownloads) this.getWebDriver();
// confirm that downloads are enabled, else fail fast
Assertions.assertTrue(downloadManager.isDownloadsEnabled(), "Managed downloads are not enabled in this session...");
logger.info("Downloading is enabled for this session `{}`...", this.getWebDriver());
// wait until the list of downloadable files is not empty
// NOTE: this will work for single file download, may face issues later when downloading multiple files
new SynchronizationManager(this).untilCustomTimeout(SynchronizationManager.uiProcessingTimeout,
        d -> !downloadManager.getDownloadableFiles().isEmpty());
logger.info("Found `{}` downloadable file(s)...", downloadManager.getDownloadableFiles().size());
// download the files from the grid to the local downloads directory
downloadManager.getDownloadableFiles().forEach(downloadableFile -> {
    try {
        downloadManager.downloadFile(downloadableFile, Path.of(BrowserFactory.getDownloadPath()));
        foundDownloadedFiles[0] = true;
        logger.info("Downloaded `{}` from remote grid to `{}` on the local machine...", downloadableFile, Path.of(BrowserFactory.getDownloadPath()).toString());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
});

for your convinence this can be simplified down to these two lines of code

var downloadManager = (HasDownloads) this.getWebDriver();
downloadManager.downloadFile(downloadableFile, Path.of(BrowserFactory.getDownloadPath()));

the first line casts a simple Webdriver driver; object that has been initialized to connect to the grid. The grid is configured correctly to enable downloads.

the second line tries to download the file by passing the file name and target location.

Exception Details

As of today (16/12/2025) when I use selenium-java 4.38.0 it works fine, and when I change the version number to 4.39.0 the following exception is thrown.

(Note: nothing else is changed; same machine, same grid instance, same code, same everything, only the selenium-java version number)

unknown command: unknown command: session/a42d018e84d0a3c35c8866528b77e6ec/se/files/titanic.csv
Build info: version: '4.39.0', revision: '126f156aee'
System info: os.name: 'Windows 11', os.arch: 'amd64', os.version: '10.0', java.version: '21.0.9'
Driver info: org.openqa.selenium.remote.RemoteWebDriver$ByteBuddy$Tc7u0OLo$ByteBuddy$dn11cEDn
Command: [a42d018e84d0a3c35c8866528b77e6ec, getDownloadedFile {name=titanic.csv}]
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 142.0.7444.59, chrome: {chromedriverVersion: 142.0.7444.59 (4b8153ab58d3..., userDataDir: /tmp/.org.chromium.Chromium...}, fedcm:accounts: true, goog:chromeOptions: {debuggerAddress: localhost:43957}, goog:processID: 222, networkConnectionEnabled: false, pageLoadStrategy: none, platformName: linux, proxy: Proxy(), se:cdp: ws://localhost:4444/session..., se:cdpVersion: 142.0.7444.59, se:containerName: 5ac8e55c5897, se:deleteSessionOnUi: true, se:downloadsEnabled: true, se:gridWebSocketUrl: ws://localhost:20347/sessio..., se:noVncPort: 7900, se:vnc: ws://localhost:4444/session..., se:vncEnabled: true, se:vncLocalAddress: ws://172.18.0.5:7900, setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 120000}, unhandledPromptBehavior: dismiss and notify, webSocketUrl: ws://localhost:4444/session..., webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:extension:minPinLength: true, webauthn:extension:prf: true, webauthn:virtualAuthenticators: true}
Session ID: a42d018e84d0a3c35c8866528b77e6ec
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
        at org.openqa.selenium.remote.ErrorCodec.decode(ErrorCodec.java:167)
        at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:142)
        at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:215)
        at org.openqa.selenium.remote.TracedCommandExecutor.execute(TracedCommandExecutor.java:53)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:561)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:638)
        at org.openqa.selenium.remote.RemoteWebDriver.downloadFile(RemoteWebDriver.java:733)
        at com.carbon.ise.ui.engine.Bot.lambda$fetchDownloadedFiles$49(Bot.java:931)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
        at com.carbon.ise.ui.engine.Bot.fetchDownloadedFiles(Bot.java:929)
        at com.carbon.ise.ui.engine.debug.steps.DebuggingSteps.iDownloadTheCsvFile(DebuggingSteps.java:52)
        at ?.I download the CSV file(classpath:engine/debug.feature:19)

in the above snippet titanic.csv is the name of the file I'm downloading.

Initial investigation

The stacktrace points to this line of code in version 4.39.0

Image

as per the below screenshot, comparing with 4.38.0 (the working version) shows that the command being called has changed from downloadFile (below) which was working, to getDownloadedFile (above) in 4.39.0 which is not working.

Image

I traced this change back to this specific PR: #16627
as seen in the changes list here
https://github.com/SeleniumHQ/selenium/pull/16627/changes

Selenium Grid details; the final puzzle piece

I checked my grid version, even though I am setting latest in my grid-compose file, it seems that the grid containers are cashed from Selenium Grid 4.38.0 (revision 6b412e825c)

I upgraded the grid compose file to mention explicitly image: selenium/hub:4.39.0 instead of image: selenium/hub:latest to ensure that I'm on the latest grid

Now, after running my test against this version Selenium Grid 4.39.0 (revision 126f156aee) the exception changes to

java.nio.file.NoSuchFileException: C:\Users\MohabMohie\GitHub\kantar\ise-uiautomation\downloads\titanic.csv
        	at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85)
        	at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
        	at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
        	at java.base/sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:234)
        	at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:482)
        	at java.base/java.nio.file.Files.newOutputStream(Files.java:227)
        	at java.base/java.nio.file.Files.copy(Files.java:3140)
        	at org.openqa.selenium.remote.RemoteWebDriver.downloadFile(RemoteWebDriver.java:737)
        	at com.carbon.ise.ui.engine.Bot.lambda$fetchDownloadedFiles$49(Bot.java:931)
        	... 4 more

tracing that stacktrace shows that the real culprit was not the change in command name (though this is a breaking change and should be highlighted on release notes!) but rather the change that was made to handle moving the downloaded files...

in 4.38.0 it was the below, which was working fine:

String contents = ((Map<String, String>) response.getValue()).get("contents");
Zip.unzip(contents, targetLocation.toFile());

now in 4.39.0 it is the following, which is not working:

Contents.Supplier content = (Contents.Supplier) response.getValue();
try (InputStream fileContent = content.get()) {
  Files.copy(new BufferedInputStream(fileContent), targetLocation.resolve(fileName));
}

I believe this is a minor error, and could easily be resolved by adding this small line of code to create the parent directories before attempting to copy the file into it. Which closely matches the old/expected behavior, without causing any new exceptions if the target parent directory had already existed.

Contents.Supplier content = (Contents.Supplier) response.getValue();
try (InputStream fileContent = content.get()) {
  Files.createDirectories(targetLocation);
  Files.copy(new BufferedInputStream(fileContent), targetLocation.resolve(fileName));
}

I will open a PR to implement this quick fix and will ask @asolntsev and @diemol to review, since they created/merged the original PR.

Highlights

I checked the release notes: https://github.com/SeleniumHQ/selenium/releases/tag/selenium-4.39.0
And the details for Java: https://github.com/SeleniumHQ/selenium/blob/trunk/java/CHANGELOG

I didn't see any mention for a breaking change with this update. I think maybe there is an assumption that no one was using this feature since it's new and not yet documented. But please note that a lot of people are eagerly awaiting the latest features and BiDi implementations, myself and my team included.

Kindly be mindful of that in future releases by either explicitly mentioning the breaking changes, or using the @Beta annotation to let us know that something may be changed without warning so that we can jump on it when it does without needing the thorough investigation.

Reproducible Code

mentioned above

ℹ️ Last known working version: 4.38.0

Metadata

Metadata

Assignees

Labels

B-gridEverything grid and server relatedC-javaJava BindingsI-defectSomething is not working as intendedI-regressionSomething was working but we "fixed" it

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions