Async-storage: AsyncStorage Couldn't read row 0, col 0 from CursorWindow

Created on 15 Feb 2019  路  9Comments  路  Source: react-native-async-storage/async-storage


This issue was originally created by @JAStanton as facebook/react-native#12529.


### Description

When reading values that are too large using AsyncStorage on Android I run into this error:

I wrote a large value with AsyncStorage and later tried to read it, but it crashed.

BaseError: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
  at e (/node_modules/react-native/Libraries/Storage/AsyncStorage.js:423:22)
  at None (/node_modules/react-native/Libraries/Storage/AsyncStorage.js:416:71)
  at map ([native code])
  at errors (/node_modules/react-native/Libraries/Storage/AsyncStorage.js:416:51)
  at slicedToArray (/node_modules/react-native/Libraries/Storage/AsyncStorage.js:54:33)

Reproduction

It looks like on iOS we write to disk when the value is above a threshold and on Android we write to sqllite always.

let x = 'x';
while (x.length <= 3194304) {
  x = `${x}${x}`;
}
await AsyncStorage.setItem('@@GARBAGE@@', x); // works
const garbage = await AsyncStorage.getItem('@@GARBAGE@@'); // throws

Solution

In order for me to fix this I'll need to re-write AsyncStorage to write to disk instead of writing to sql. https://github.com/mvayngrib/react-native-safe-async-storage <--- this guys has the right idea but his code is super old and broken.

Additional Information

  • React Native version: 0.39.2
  • Platform: Android
  • Operating System: Samsung Galaxy S4
bug enhancement help wanted Android

All 9 comments

Workaround:

async getSafeItem(key) {
  return new Promise((resolve, reject) => {
    if (!key) {
      reject('Invalid key');
    }
    AsyncStorage.getItem(createKey(key)).then((value) => {
      resolve(value);
    }, () => {// Couldn't read row 0, col 0 from CursorWindow
      resolve(null); // Force not to break
    });
  });
}

Additional Information

  • React Native version: 0.57.0
  • Platform: Android
  • Operating System: All Motorola devices

@Krizzu why API: AsyncStorage label was removed if it is related?

@juliopiubello Because this whole module is about AS. Since everything is related I just remove redundant labels

@juliopiubello were you able to solve it? I'm having the same issue

According to this comment on SO, CursorWindow size limit is 2MB per row (I couldn't find official docs saying that but let's assume it for now).

Repro steps by OP gives us a 4194304 length string. According to ECMAScript specification, each character takes 2 bytes of memory, so whole is something around 8.38 MB.

This is way over the limit of CursorWindow, hence the crash.

Now, to work around this:

  • Try not to store your whole object as a single entity (by stringifying objects) - divide it into smaller pieces, then store in at different AS keys

  • Write a helper that will save large data into filesystem, instead to AS

thanks.

2MB seems to be correct. CursorWindow's default constructor just pulls the number from the internal configuration.

@Krizzu Would it make sense to have a warning here in dev mode to make people more aware of the limitation?

@tido64 You mean like checking for string length before calling Native Module? We could do it, I can imagine those JSON strings parsed all the time :)

If you need more help with this particular issue, please do let us know.

https://github.com/react-native-community/async-storage/pull/99
will this update help me to over the limit of CursorWindow?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alex-mironov picture alex-mironov  路  71Comments

Waqas-Jani picture Waqas-Jani  路  28Comments

michaelsinatra picture michaelsinatra  路  24Comments

dominiczaq picture dominiczaq  路  22Comments

Alaa-Ben picture Alaa-Ben  路  20Comments