Change In ArrayExpressions support in CBL between 2.1.5 and 2.5

I have a CBL query that uses ArrayExpressions. It worked perfectly in 2.1.5, but fails with “datatype mismatch” in 2.5.

All of my local documents have a channels array (“channels”). In the code below, I have a separate array containing a set of channel names I’m looking for (“hunt_channels”). I want to find any documents where any entry from the channel array matches any entry from the hunt_channels list, and return a list of their IDs.

So if hunt_channels = [“a”, “b”, “c”]
and my documents are:
doc1: { channels: [“d”], …}
doc2: { channels: [“b”, “e”], …}
doc3: { channels: [“a”], …}
the search should return doc2, doc3.
I was guided in the creation of this code by this excellent document on ArrayExpressions:

The code works like this:
We create an array of IExpressions containing the channel values I am looking for (channel_list).
Then we create a variable to represent each element of the channels for each document (channel_variable).
And we look for documents that satisfy channel_variable in channel_list.

This works well and is fast in CBL 2.1.5.
This generates a “datatype mismatch” exception in CBL2.5. I’ve included the exception details at the bottom.
Have I done something stupid?

Here is the code:

        public List<string> ListDocumentsWithChannelAccess(List<string> hunt_channels)
        {
            List<string> ids = new List<string>();
            try
            {
                var channel_variable = ArrayExpression.Variable("the_channel");
                IExpression[] channel_list = new IExpression[hunt_channels.Count];
                for (var i = 0; i < hunt_channels.Count; i++)
                    channel_list[i] = Expression.String(hunt_channels[i]);

                var query = QueryBuilder.Select(SelectResult.Expression(Meta.ID))
                   .From(DataSource.Database(database))
                   .Where(ArrayExpression.Any(channel_variable)
                        .In(Expression.Property("channels"))
                        .Satisfies(channel_variable.In(channel_list)));

                foreach (var result in query.Execute())
                {
                    var id = result.GetString("id");
                    ids.Add(id);
                }
            }
            catch (Exception e)
            {
                log.Error(e, "Failure in listing documents");
            }
            return ids;
        }

It fails with the exception at the query.Execute().
The exception details are:

Couchbase.Lite.CouchbaseSQLiteException: CouchbaseLiteException (SQLiteDomain / 20): datatype mismatch.
  at LiteCore.Interop.NativeHandler.ThrowOrHandle () [0x00089] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\NativeHandler.cs:257
  at LiteCore.Interop.NativeHandler.Execute (LiteCore.Interop.C4TryLogicDelegate2 block) [0x0002c] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\NativeHandler.cs:203
  at LiteCore.LiteCoreBridge.Check (LiteCore.Interop.C4TryLogicDelegate2 block) [0x00000] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\LiteCoreBridge.cs:57
  at Couchbase.Lite.Support.ThreadSafety.DoLockedBridge (LiteCore.Interop.C4TryLogicDelegate2 a) [0x00011] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\Couchbase.Lite.Shared\Support\ThreadSafety.cs:72
  at Couchbase.Lite.Internal.Query.XQuery.Execute () [0x00059] in C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\Couchbase.Lite.Shared\Query\XQuery.cs:417
  at CoreLibrary.DB.ListDocumentsWithChannelAccess (System.Collections.Generic.List`1[T] channels) [0x000c2] in /Users/Paul/Dev/CoreLibrary/DB.cs:971

Side Note: the original reason for this code is that prior to 2.5, you had to manually remove local documents if you lost access to their channel from the server end (i.e. your list of accessible channels changed at the server). This code looks for docs I no longer have access to so I can manually remove them, and I run it when I notice any channel access changes.

In 2.5, one of the awesome new features is “Automatic purge of removed documents”. In theory I shouldn’t need this function going forward. Sadly, for some reason, local docs that I no longer have access to are not being removed. However I haven’t tracked that down yet so am loathe to report a bug until I’m sure.

This is a known issue that is currently being worked on. A 2.5.2 will be released (most likely this month) addressing it. There is a workaround but it is a bit of a pain. You basically need to read all the documents out of the database and into a new one so that they are saved in a way that doesn’t cause this issue.

Whew… thought I was going a little crazy here.
Thanks for the speedy response and pointer to the bug report.