WatermelonDB
WatermelonDB copied to clipboard
Recommended way to alert users their disk is full
Hello,
How can I catch the "no space left on device" error in order to alert my users? When running out of disk space, I can see the following in my logs :
[libsqlite3.dylib] os_unix.c:40550: (28) seekAndWrite(/.../test.db-wal) - No space left on device
[libsqlite3.dylib] os_unix.c:40640: (28) unixWrite(/.../test.db-wal) - No space left on device
[Flow] Error: Failed to execute db update - sqlite error 13 (database or disk is full)
[Flow] Error: Error while attempting to roll back transaction, probably harmless: Failed to execute db update - sqlite error 1 (cannot rollback - no transaction is active)
However I didn't manage to catch it, it seems to be only printed and not throwed. I tried .catch()
on database.write()
and I tried catching all unhandled rejections but it doesn't seem to work. Am I missing something?
I think it would be convenient to register a global error callback that receives this kind of errors, so we can alert the end user.
@arcln I can give you the hints on how to configure this, but you'll send a pull request with updated docs to help others with this in the future. deal?
deal
@arcln
- You need to have JSI enabled (I think you do) - it's
jsi: true
to the adapter constructor, and details are documented in the installation docs - then you need to add an error listener, like so:
adapter._dispatcher._unsafeErrorListener = async (error) => {
if (
error &&
typeof error.message === 'string' &&
error.message.includes('database disk image is malformed')
) {
// ...
}
}
I don't know what exact error message is passed in case of no space left, so you can just add console.log(error) to figure it out and adjust the condition. But I'm quite sure that disk full error should successfully propagate here
- Unfortunately, the SQLite adapter is not capable of gracefully handling such an error, i.e. the database will not function correctly after encountering this error. So best we can do is alert the user of the issue so they can resolve it… and once they do, we need to reload the app (reload react native bridge) - if they just come back and we don't reload, it will be somewhat broken
Hello, I tried this method but it doesn't work.
My code:
const adapter = new SQLiteAdapter({
dbName: 'file:/tmp/test/test.db', // very small partition
jsi: true,
schema,
migrations,
});
adapter._dispatcher._unsafeErrorListener = (error) => {
console.log('catched something');
};
When I trigger the "no space left" error, I can see sqlite logging the problem but my callback is not fired.
@arcln That doesn't sound right… I looked at the code and it should propagate correctly here.
Are you using iOS or Android? Are you familiar with how to set breakpoints in Xcode/Android Studio?
Hello, sorry for late response. I'm not familiar with native debugging and I don't have much time to dig into it. Just wanted to give an update to this.
I did not manage to catch the error and I believe I should not try to do so. It can happen at many layers in very different places (even outside of the database) and it would be a pain to catch all of them - if it's even possible.
So I ended up writing a piece of code that periodically checks remaining disk space, and whenever the space is ridiculously low, alert the user he may encounter unexpected behaviour if he doesn't free up some space.