electron: The fs API doesn't work in a renderer process unless the BrowserWindow has been reloaded once
Preflight Checklist
- I have read the Contributing Guidelines for this project.
- I agree to follow the Code of Conduct that this project adheres to.
- I have searched the issue tracker for an issue that matches the one I want to file, without success.
Issue Details
- Electron Version: 5.0.8
- Operating System: Windows 10 (1809)
- Last Known Working Electron version: 3.1.12
Expected Behavior
Calling the asynchronous fs APIs should work in the renderer process in the same way that it works in the main process.
Actual Behavior
Calls to the asynchronous fs APIs in the renderer process will randomly fail. No exception is thrown, rather, it seems like the callback is never called when using the old asynchronous API and the awaited promise will never complete when using the newer fs.promises API. The synchronous API seems to work consistently.
I have observed this error with code like:
const fs = require("fs");
// Sometimes this callback will never be called
fs.stat("C:\\", () => {});
// Sometimes this will await forever
await fs.promises.stat("C:\\");
// This always seems to work
fs.statSync("C:\\");
While I use stat in the example above, I’ve also observed it with readFile and writeFile. I’ve also observed the issue on a variety of paths, not just “C:\”. The issue seems to go away if I refresh the browser window. So I’ve refactored my application in the short term to refresh the browser window after initial load. I’ve added a branch to renderer.js similar to:
const electron = require("electron");
if (electron.remote.getCurrentWindow().hasReloaded) {
// Run renderer logic
} else {
electron.ipcRenderer.send("needs-reload");
}
Then in the main process I do:
const electron = require("electron");
let browserWindow;
electron.ipcMain.on(
"needs-reload",
() => {
browserWindow.hasReloaded = true;
browserWindow.reload();
}
);
// Run main logic, including creating browserWindow.
To Reproduce
See my notes above, let me know if you’d like more information.
Additional Information
It looks like this issue in nodejs is also observing the problem https://github.com/nodejs/node/issues/14889.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 15
- Comments: 38 (5 by maintainers)
Commits related to this issue
- Promise not resolved https://github.com/electron/electron/issues/19554 — committed to brafdlog/caspion by baruchiro 4 years ago
- fix fs module hanging not allowing code to run Run button on Windows stopped working as CodeRunner was hanging when executing fs.promises.mkdir as described in electron/electron#20951 It started happ... — committed to undergroundwires/privacy.sexy by undergroundwires 3 years ago
- fix fs module hanging not allowing code to run Run button on Windows stopped working as CodeRunner was hanging when executing fs.promises.mkdir as described in electron/electron#20951 It started happ... — committed to undergroundwires/privacy.sexy by undergroundwires 3 years ago
- Fixed electron issue with FS https://github.com/electron/electron/issues/19554 — committed to equilaterus-gamestudios/utility-ai-configurator by dacanizares 3 years ago
- fix fs module hanging not allowing code to run Run button on Windows stopped working as CodeRunner was hanging when executing fs.promises.mkdir as described in electron/electron#20951 It started happ... — committed to LarrMarburger/privacy.sexy by undergroundwires 3 years ago
I’m gonna go ahead and close this out - if there are new issues please open them in a new issue!
This issue has been driving me crazy after upgrading my app from Electron 3.0.14 to 6.0.12, and I’ve been trying unsuccessfully for days to get a minimal reproduction. It is not limited to dev mode, it also shows in the final packaged app.
However, after reading the thread and doing some experiments, it definitely seems like a
BrowserWindow.loadURLrace condition / timing issue.The issue reliably appears on my dev machine with the following code in main.ts:
and reliably disappears when changing the line to the following, or after reloading:
Environment: Electron 6.0.12, Typescript, Windows 10
This is a problem for me to running on electron 9.1.0
Using Visual Studio code and Windows 10
setTimeout() fixed the problem for me.
So glad this issue was here, without it I probably would have just given up on 20+ hours worth of app coding.
I recently ran into this issue while using Spectron with Electron(v11.2.1). Our application loaded fine on its own but had this(or a similar) issue when loaded with Spectron. It was odd because everything had been working fine and nothing in our codebase had changed(i.e. literally 0 changes).
I tried upgrading to v12.0.10 but had no luck. However, I noticed there was an update to malware definitions in Windows defender.
What ended up fixing it for us was turning off Real-time protection in Windows Defender. Hopefully, this is helpful to someone.
This should be fixed by https://github.com/electron/electron/pull/25869
@codebytere Could you please explain why you’re closing this issue?
As far as I can say, the issue is not fixed and your proposed fix is not related to the initial issue at all.
None of the suggested workarounds worked for me:
setTimeout(() => { win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) }, 100);I am testing with
fs.promises.lstat. Starting from the second invocation, the promise does not resolve. This reproduces reliably. Tested with Electron 9.0.0. Same behavior with Electron 10.1.0.What does work for me is to use node APIs only in the main process. I use the messaging mechanism to invoke node APIs from the renderer process:
This is more work, but it is well worth the trouble. It works reliably and without workarounds.
The Electron documentation advertises the use of Node.js APIs in the renderer process:
According to this issue, at least the
fsAPI has been broken for at least a year. How about changing the documentation to say that the recommended, reliable practice is to call Node.js APIs (or at least thefsAPI, if the issue is limited to that) only from the main process, and to expose APIs to the renderer process as shown above? This is recommended for security reasons, anyways, right? Maybe we could even deprecate the use of Node.js APIs from the renderer process altogether?What do you think?
Issue persists with Electron 8.2.2 on Windows 10 with electron-forge @Doccrazy 's timeout trick solved it for me.
Some additional observations for the devs:
Calling loadURL on the very next tick results in expected callback behavior, no matter what allowRendererProcessReuse is set to. Race condition indeed.
The resulting executables in this Electron version work without the timeout trick at all.
Occurs also in Electron v14.0.0. Hangs indefinitely on
fs.promises.readFileuntil the page is reloaded. Occurs randomly but very often, about 50% of the time.Yeah, we also experienced issues when using Axios. The request just disappears.
But I’M NOT AbLE TO reprODucE IT oN any PLaTfOrM, And HAVE NoT SEen A rePro wHIch HAs ALLOwed mE TO Do so.
¯_(ツ)_/¯
The whole point of this issue is that it’s notoriously difficult to reproduce and the cause cannot easily be isolated.