react-native-fs icon indicating copy to clipboard operation
react-native-fs copied to clipboard

RNFS.writeFile() -> ENOENT: open failed: EEXIST (File exists) - if file is deleted manually

Open Bilal-Abdeen opened this issue 3 years ago • 16 comments

On a real Android device, RNFS.writeFile() fails saying ENOENT: open failed: EEXIST (File exists), while RNFS.exists() returns false. This occurs after the file was created by the app, and then deleted manually from the file system. This problem does NOT occur on an Android emulator.

Scenario to reproduce: ON A REAL DEVICE:

  1. Use RNFS.writeFile() to create a file
  2. Using a file access software, e.g. Google Files, delete the created file (above).
  3. Try to re-create the file again using RNFS.writeFile()
  4. You get an error ENOENT: open failed: EEXIST (File exists), while it has been deleted, and the result of RNFS.exists() confirms that it is not there?!

Device Infomation:

Samsung Galaxy S10+ 
Android Version: 11
One UI Version: 3.1
Google Play system update: 1 August 2021
Kernel version: 4.14.113.22340597
#1 Wed Dec 1 11:14:06  KST 2021 

Code:

try {
	const fileExists = await RNFS.exists(fullPath); 
	console.log("fileExists:", fileExists, "fullPath:", fullPath, ); // fileExists: false  - fullPath: /storage/emulated/0/Download/myFileName.csv

	if (fileExists) {
                // Execution never reaches this point 
                console.log("inside if statement", ); 
		await RNFS.unlink(fullPath); 
		console.log("file deleted");
	}

        // The following statement triggers the catch (below) 
	await RNFS.writeFile(fullPath, fileContents, "utf8");

	// execution never reaches this point 
	console.log("file Written");
}
catch (err) {
	console.error("err:", err ); //  err: [Error: ENOENT: open failed: EEXIST (File exists), open '/storage/emulated/0/Download/myFileName.csv']
}

Versions:

    "react-native": "0.66.4",
    "react-native-fs": "^2.18.0",

Bilal-Abdeen avatar Feb 12 '22 02:02 Bilal-Abdeen

I'm seeing this issue as well. Not only with RNFS writes in my case, it is also seen with file writes from the backend so may not be fixable in react-native-fs. It does appear to happen when files have been manually deleted.

If I change the file name to a previously unused one, it works normally, so it definitely is related to a deleted file.

I have tried deleting the whole folder containing the files, and also subsequently emptying the recycle bin, but the errors still occur unless I change to a new filename. My versions are the same as above:

    "react-native": "0.66.4",
    "react-native-fs": "^2.18.0",

nigelorr avatar Feb 18 '22 12:02 nigelorr

it happens with appendFile as well...

zabojad avatar Mar 24 '22 22:03 zabojad

Any updates?

szyymoon avatar Mar 31 '22 12:03 szyymoon

Fixed by this way:

  1. add to the AndroidManifest.xml
<application android:requestLegacyExternalStorage="true"`
  1. request permission:
const requestWritePermission = async () => {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log('You can use the write');
      return true;
    } else {
      console.log('write denied');
      return false;
    }
  } catch (err) {
    Alert.alert(err.message);
    return false;
  }
};

AleksandrStelchenko avatar Mar 31 '22 14:03 AleksandrStelchenko

Instead of deleting the previous file and creating a new one, create a new named file each time. like adding random numbers at the end of the file name. You can do that with using libraries such as nanoid.

const uri = RNFS.ExternalStorageDirectoryPath + `/filename-${nanoid()}.txt`;

Of course, this can turn the user storage space into a garbage, depending on how often you use it.

Kaosc avatar Jul 02 '22 22:07 Kaosc

Having the same issue with RNFS.copyFile(). Here is some extra information that may help someone:

Device Infomation:

Samsung Galaxy A50
Android Version: 11
One UI Version: 3.1
Google Play system update: October 1, 2022
Kernel version: 4.14.113-113-21578199
#1 Fri Sep 16 15:21:34  KST 2022

Code

try {
    RNFS.copyFile(src, dest); // Where dest is a file that has been deleted manually via My Files app.
} catch (error)
    console.error(error.message); // ENOENT: open failed: EEXIST (File exists), open `/storage/emulated/... (dest location)`.
}

Versions

    "react-native": "0.64.4",
    "react-native-fs": "2.20.0",

ryanshepps avatar Nov 23 '22 18:11 ryanshepps

I believe that android caches the filenames even after you delete them. I have Android File Manager and when I delete a file through there and close the app I am able to save the file with the same name successfully. If I delete the file from the file manager on the device and try to resave with the same name then it throws the "already exists" error.

NathanNovak avatar Dec 30 '22 18:12 NathanNovak

I came across this using cordova-plugin-file-transfer - and the same behavior. The file downloaded fine, then I manually deleted from phone using File Manager app. After that I couldn't download the file again. My app has all the permissions and has <application android:requestLegacyExternalStorage="true">

Drove me nuts trying to understand the issue until I found this thread.

What I don't understand is why Android cares if the file already exists...why not just over write it? Seems a bug that if a user deletes a file and Android caches the name to never be used again. Makes no sense.

rolinger avatar Aug 31 '23 14:08 rolinger

@NathanNovak - whats the difference between Android File Manager and some other device app File Manager? Seems if we can figure out what the Android one is doing we could replicate that in our code. Like, how do we delete the file name from (what appears to be) Android's cached list?

rolinger avatar Aug 31 '23 14:08 rolinger

Another thing to note. After the user manually deletes the file, my app reading the device directory path shows the file does not exist. But when trying to write the file with the same name again, it shows it as existing

rolinger avatar Aug 31 '23 15:08 rolinger

Just hit the manually deleted file issue. In my case it seems that if i have "Trash folder" enabled, after clearing it the file is writable again. You could also turn off using a trash folder altogether (maybe not available depending on the Android OS variant You use). This without adding any permission requests, nor legacy flags.

dferenc-netwizzy avatar Sep 12 '23 10:09 dferenc-netwizzy

Is there any solution? I have the same problem. If I delete the file manually, this error appears.

batu-han3428 avatar Feb 19 '24 18:02 batu-han3428

the file still exists in recycle bin which causes the error. Delete the file from there and try downloading it again it should work fine.

mehranjavid avatar Feb 24 '24 21:02 mehranjavid

the file still exists in recycle bin which causes the error. Delete the file from there and try downloading it again it should work fine.

As noted above (Feb 18 2022), deleting from the recycling bin does not clear this. The system still retains 'memory' of the file somewhere

nigelorr avatar Mar 05 '24 12:03 nigelorr

the file still exists in recycle bin which causes the error. Delete the file from there and try downloading it again it should work fine.

As noted above (Feb 18 2022), deleting from the recycling bin does not clear this. The system still retains 'memory' of the file somewhere

Idk, I was getting this last week tried deleting the file from recycle bin and it worked. I did test this again and again and every time after deleting the file from recycle bin it allowed me to download with the same name. my project contains following versions. "react-native": "0.73.1", "react-native-fs": "^2.20.0", // this is same i see Samsung A33

maybe this issue varies from device to device.

mehranjavid avatar Mar 05 '24 12:03 mehranjavid