Search code examples
nearprotocol

"The collection is an inconsistent state." with nested NEAR collection


I've run into an issue where having a nested NEAR collection (in this case TreeMap) can give this error:

The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?

The struct I'm using looks like this:

pub struct CollectionIssues {
    nested_treemap: TreeMap<AccountId, TreeMap<u128, String>>,
}

Then we:

  1. Add entries to both the inner and outer TreeMaps.
  2. Remove the out TreeMap's key (here it would be an AccountId)
  3. Try re-adding the same entry.
  4. Receive the error mentioned above.

I've provided a demonstration repository here:

https://github.com/mikedotexe/near-collections-issue

To reproduce, clone and run ./test.sh


Solution

  • The issue is how TreeMap is created. When initializing a collection, you need to specify the unique prefix. By default it uses global auto-increment. When the collection is saved to the state, it's prefix is also saved to the state, but global auto-increment counter is not persisted. So when you reinsert a new map, it uses auto-increment prefix value that is not unique and collides with the existing collection.

    The best way to avoid it is to give a unique prefix for every TreeMap created using TreeMap::new(unique_prefix). The unique prefix in your case can be env::sha256(account_id) for the key in the first collection.

    Example of this is in FungibleToken implementation: https://github.com/near/near-sdk-rs/blob/ac8c849fba6b912a5ef46d156662b3e1f6b56894/examples/fungible-token/src/lib.rs#L43

    Notice how the allowances map is initialized there for a given account.