electron-store: Operation not permitted
Got the following error from Sentry produced by our production app. Could this be due to some odd permissions that the user has changed on their system?
OS: Windows 10.0.17763 Electron: 8.0.0 electron-store: 3.3.0
Error: EPERM: operation not permitted, rename 'C:\Users\mattd\AppData\Roaming\clockk\config.json.2393936311' -> 'C:\Users\mattd\AppData\Roaming\clockk\config.json'
at Function.writeFileSync [as sync](app:///node_modules/write-file-atomic/index.js:198:8)
at ElectronStore.set store [as store](app:///node_modules/conf/index.js:267:19)
at ElectronStore.set(app:///node_modules/conf/index.js:152:14)
at _.clearArtifacts(app://./js/app.1a7ce22d.js:1:20601)
at ? (app://./js/chunk-vendors.3f748be6.js:38:5706)
at ? (app://./js/chunk-vendors.3f748be6.js:38:6751)
at Array.forEach(<anonymous>)
at ? (app://./js/chunk-vendors.3f748be6.js:38:6730)
at _._withCommit(app://./js/chunk-vendors.3f748be6.js:38:8276)
at _.commit(app://./js/chunk-vendors.3f748be6.js:38:6704)
at _.commit [as originalCommit](app://./js/chunk-vendors.3f748be6.js:38:3374)
at EventEmitter.<anonymous>(app://./js/chunk-vendors.3f748be6.js:85:28802)
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 1
- Comments: 41 (4 by maintainers)
@sindresorhus Here we go (hopefully): https://github.com/fabiospampinato/atomically
I’m basically on your same boat and I couldn’t find anything better than
write-file-atomic, so I rewrote it. I’d sayatomicallyis probably strictly better thanwrite-file-atomic, it handles more errors (including the one mentioned here), it can be 10x faster on synchronous writes and just as safe (I’ve no idea why in my benchmark it isn’t also 10x faster in asynchronous writes), it has way more options (including a way to hide temporary files) etc.On the code quality I can’t comment too much being the author of this one, but at least when putting the async and sync version of the provided functions side by side the implementation is basically identical, in
write-file-atomicthere are a bunch of quirks because this isn’t true there too. Unfortunately the test suite is still pretty messy as I inherited the one fromwrite-file-atomic, but throwing their tests away didn’t feel right and rewriting the entire test suite didn’t feel worth it.Happy to work on any eventual issue you guys can find, I’m going to use this library in an Electron app too so any issue you can find I’ll be interested in fixing it.
I’ve been doing some research. I think it boils down to the fact that Windows API for rename is very unstable and depends on a lot of factors like anti-virus, any open file handles, and the moon phase.
electron-storeis usingwrite-file-atomic, which uses the plain Node.jsfsapi. I think for this to be improved,write-file-atomicneed to instead usefs-extra(which handles the EXDEV issue #106) and it usesgraceful-fswhich handles the EPERM issue with a 1 second retry loop.One problem is that even with
graceful-fsthere are still issues with EPERM on windows even though it has 1 second retry logicAnd I don’t think the
write-file-atomicguys want to use introduce two extra layers of abstraction by addingfs-extradependency, becausewrite-file-atomicis being used by a lot of packages includingnpmand it might introduce regressions for a lot of people.So I think either electron-store needs to either:
platform.os === 'win32')EPERMto the catch block if-check along withEXDEVto retry with fs.writeFileSync. I’m not sure if this will work because EPERM seems to be caused by the target file being occupied by antivirus or something else for some time, and I’m not sure if writeFileSync will also throw EPERM if the file is still occupiedfs-extrawhich better handles these errors.electron-storeREADME about the fact that thesetandnew Store()functions is likely to fail often on Windows and that they need to handle this in their code with try/catch around these functionsReleased: https://github.com/sindresorhus/electron-store/releases/tag/v6.0.0
Yes, you can replace it as-is. But only thing changed is the timeout (from 100ms to 500ms) that is given to the operating system for finishing the write operation. In other words, we allow the operating system more time to do the write operation before aborting.
@bad2Dbone It sounds like you are using a version with
atomicallyalready, in that case there isn’t too much that can be done, like there are no guarantees that write operations will always succeed, especially in hostile environments like Windows with an aggressive antivirus, you might want to consider switching to asynchronous writes rather than synchronous, as the former have a higher default timeout, or you could just provideatomicallya higher up timeout is that sounds like a good trade off to you, although currently I don’t thinkconfandelectron-storeallow you to change these things 🤔@jurepetrovic There are all sorts of factors that have an impact on this, including if the sun is shining outside or not, and we can’t really do much about them, maybe in your case just having all files packages in an
asararchive makes the antivirus take longer to scan it and unlock it, even if the part of the archive being scanned is not the one you currently care about. But I don’t think you are writing into theasarso probably that doesn’t matter 🤔https://www.npmjs.com/package/electron-store-atomically
If we merge this successfully and it works under windows, I’d be very happy to use this original package!
I have made PR #130 , but it requires some more testing for real production. Actually the real change is in conf-atomically, where the atomically is actually used.
I had to change some project data, since I published separate npm package on npmjs for our own use.
Thanks and Rgds, Jure
I’ve once again read the doc of this proj, and this time I found something may be good for you (and for me, too). Haven’t tested myself, though I’m thinking that by using this, your code may need to be complex.
Anyway, I think for using this lib, try-catches are necessary (and it also seems to be the most convenient and least costly solution to partially fix this?) to make your code stronger…