17

I'm using AsyncStorage.clear() which is working just fine on Android but when run using iOS platform (real device) I'm getting this error and can't find anything online about it.

Error: Failed to delete storage directory.Error Domain=NSCocoaErrorDomain Code=4 "“RCTAsyncLocalStorage_V1” couldn’t be removed." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/281A6456-6CB2-47D4-AD04-3EB26A1B9506/Documents/RCTAsyncLocalStorage_V1, NSUserStringVariant=(
    Remove
), NSUnderlyingError=0x174049480 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
Error: Failed to delete storage directory.Error Domain=NSCocoaErrorDomain Code=4 "“RCTAsyncLocalStorage_V1” couldn’t be removed." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/281A6456-6CB2-47D4-AD04-3EB26A1B9506/Documents/RCTAsyncLocalStorage_V1, NSUserStringVariant=(
    Remove
), NSUnderlyingError=0x174049480 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
    at convertError (http://192.168.1.33.xip.io:8081/index.ios.bundle?platform=ios&dev=true&minify=false:52255:13)
    at http://192.168.1.33.xip.io:8081/index.ios.bundle?platform=ios&dev=true&minify=false:52109:18
    at MessageQueue.__invokeCallback (http://192.168.1.33.xip.io:8081/index.ios.bundle?platform=ios&dev=true&minify=false:2060:16)
    at http://192.168.1.33.xip.io:8081/index.ios.bundle?platform=ios&dev=true&minify=false:1853:15
    at MessageQueue.__guard (http://192.168.1.33.xip.io:8081/index.ios.bundle?platform=ios&dev=true&minify=false:1991:9)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (http://192.168.1.33.xip.io:8081/index.ios.bundle?platform=ios&dev=true&minify=false:1852:13)
    at t (file:///Applications/React%20Native%20Debugger.app/Contents/Resources/app.asar/js/RNDebuggerWorker.js:1:14632)
bennygenel
  • 23,896
  • 6
  • 65
  • 78
Robel Robel Lingstuyl
  • 1,341
  • 1
  • 11
  • 28

3 Answers3

22

I think it's crappy that clear throws an exception when the storage has never been used; at least that is what I'm thinking is the case?

So to move on I modified code removing the use of .clear() and replacing it with AsyncStorage.getAllKeys().then(AsyncStorage.multiRemove)

I'd still like an reason if anyone knows what is going on.

Tien LX
  • 41
  • 2
  • 7
Robel Robel Lingstuyl
  • 1,341
  • 1
  • 11
  • 28
14

When AsyncStorage is empty...

AsyncStorage.clear()
errors on iOS but not Android.

AsyncStorage.getAllKeys().then(AsyncStorage.multiRemove)
errors on Android but not iOS.

Our solution...

import {  Platform } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';

const asyncStorageKeys = await AsyncStorage.getAllKeys();
if (asyncStorageKeys.length > 0) {
  if (Platform.OS === 'android') {
    await AsyncStorage.clear();
  }
  if (Platform.OS === 'ios') {
    await AsyncStorage.multiRemove(asyncStorageKeys);
  }
}
GollyJer
  • 23,857
  • 16
  • 106
  • 174
  • where would this code written? – deemyBoy Jul 18 '23 at 21:19
  • Put it in a function and call it with whatever logic you need or from wherever you want. We have it commented out in app.tsx, uncomment it and reload, then comment out. It's only for dev purposes. – GollyJer Jul 18 '23 at 22:46
  • Appreciate that and I tried it last night but...I got a warning that I needed to change my ts-config file to allow await which I did. I then got an error. I'm going to clarify those in a minute but adding the code back in. I actually don't want to use AsyncStorage in production but ExpoSecureStore but can't as I'm developing mostly in the browser and that package doesn't work on the web. I need a way to differentiate between web and Android/iOS so I can have both storage solutions coded in (without constantly commenting out either packages when switching from web/dev to prod - maybe env? – deemyBoy Jul 19 '23 at 03:46
0

I'm using an auth loop to log users in so put it just inside the Auth context which is wrapping my whole app

Here are my imports

import AsyncStorage from '@react-native-async-storage/async-storage';
import { Platform } from 'react-native';

and a bit lower down just after the AuthContext create call

const AuthContext = createContext<IAuthProps>({});

const clearStorage = async () => {
  const asyncStorageKeys = await AsyncStorage.getAllKeys();
  if (asyncStorageKeys.length > 0) {
    if (Platform.OS === 'android') {
      await AsyncStorage.clear();
    }
    if (Platform.OS === 'ios') {
      await AsyncStorage.multiRemove(asyncStorageKeys);
    }
  }
};
clearStorage();

I'm not using the community AsyncStorage package though but it still works

  • I know the function is marked async but my project was throwing an error regarding not allowing await at the top level without changing my tsconfig and I didn't want to do that due to the unknown implications of doing so!
deemyBoy
  • 65
  • 10
  • this is obviously based off GoolyJer's answer - appreciate the help from your comment in your answer to my question about where to write this code – deemyBoy Jul 23 '23 at 01:48
  • Looks good. This is what I meant by "put it in a function and call it from wherever you want". – GollyJer Jul 24 '23 at 21:53