Writing to Android persistent storage with Unity throws Read-only file system error

Hi,
I’ve added Realm to my Unity application for Android. While everything works fine now in the Editor, I ran into problems when running the app on an Android device. So far, I’ve used the persistent data path to store data on the device, and I would like to continue doing so with the Realm database. But when I try to do so I get the exception

Error Unity RealmException: Failed to create fifo at ‘realm_9223144369529052091.cv’: Read-only file system

I am using UnityEngine.Application.persistentDataPath to get the persistent storage path, and this resolves to
/storage/emulated/0/Android/data/[Package Name]/files

Here is how I initialize Realm:

    string dbPath = $"{Application.persistentDataPath}";   
    config = new RealmConfiguration($"{dbPath}/{localPlayerId}_db.realm")
    {
      IsReadOnly = false,
      SchemaVersion = 5001001
    };

    try
    {
      Realm = Realm.GetInstance(config);
    }
    catch (RealmFileAccessErrorException ex)
    {
      Debug.LogError($"Error creating or opening the realm file. {ex.Message}");
    }

Does anyone have an idea how this problem could be resolved? Does the persistent storage at this location differ somehow from the rest of the Android filesystem? Because when I just use the default path of Realm on Android, storing the db works, but of course, this is not in persistent storage then.

The default path that Realm chooses is Context.getFilesDir, which means the files there are persisted. We chose this specifically because Application.persistentDataPath on Android will sometimes resolve to a read-only folder (see this comment).

In your case though, the issue may be different - if you’re able to write regular files in the location returned by Application.persistentDataPath but not able to open a Realm in this location, it could be because the filesystem doesn’t allow creating named pipes, in which case you’ll need to set RealmConfiguration.FallbackPipePath to a path where named pipe creation is allowed (e.g. the internal data directory).

1 Like

Hi Nicola,

thanks a lot for your reply! I’ve tried it and used the same approach to get the internal data directory as you did (also described here). Adding this path to the RealmConfiguration’s FallbackPipePath did the trick.

But generally - and this is rather a Unity topic - I wonder why I shouldn’t use the internal data directory for all cases. What is the benefit of Application.persistentDataPath? As I understand it, it may point to storage on an external SD card, depending on some permission settings and whether there is an external SD card at all. /storage/emulated hides a potential FAT file system on the external SD card, and hence the problems you describe with permissions. But “how persistent” is this internal storage? Is it retained when the app is removed and installed again? Is it cloned to a new device if Google’s migration tool is used?

And another question which relates to the persistency topic: what happens if the named pipe is deleted? Is it still possible to read the Realm database? Is it recreated?

Sorry for all those questions, but I want to make sure that the game data is stored relyably on all possible devices and that I don’t need to migrate the storage location at some point in the future.

The named pipes should be recreated the next time you open the database, so deleting them is not an issue. If you attempt to delete them while in use, they’ll likely be marked for deletion, but not really deleted until the database is closed (this is OS and filesystem specific - on NTFS/windows, you’ll get an exception trying to delete the pipe).

Regarding the persistent path: yes, the internal data folder is backed up (per Google’s docs). I guess the only benefit of using the external data path over the internal one is that it’s possibly larger, but it comes with a bunch of downsides - it can be slower or on a filesystem that doesn’t support named pipes/is readonly. It’s on you to decide what is best for your users depending on the amount of data you plan to store in the database. In most cases we’ve seen, the database size is quite small compared to the game installed size, so using the internal storage is fine, but, of course, your mileage may vary.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.