Corrupt Revision Data

I am getting the following error on the c# Couchbase Lite SDK in Xamarin IOs. on both 2.8.6 and 3.0.0 beta versions.

This happens intermittently when I am querying a dataset, It happens when I try to read certain records ( but I can’t id them at all ) - For example this query below sequently reads batches of records but only will error when I get to offset 190000 - then it will not read any further data records in that set.
This is repeatable with multiple devices

What does corrupt Revision Data actually mean , Can I fix it - if so how ? Is there something to run on the main server to fix it or reset Revision Data ?

What would you like me to submit to help get to the bottom of it ?

Error Thrown.

NativeHandler.ThrowOrHandle ()

C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\NativeHandler.cs, line 250

Couchbase.Lite.CouchbaseLiteException: CouchbaseLiteException (LiteCoreDomain / 5): corrupt revision data.

  • LiteCore.Interop

NativeHandler.ThrowOrHandle () C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\NativeHandler.cs:250

  • LiteCore.Interop

NativeHandler.Execute (LiteCore.Interop.C4TryLogicDelegate2 block) C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\NativeHandler.cs:180

  • LiteCore

LiteCoreBridge.Check (LiteCore.Interop.C4TryLogicDelegate2 block) C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\LiteCore\src\LiteCore.Shared\Interop\LiteCoreBridge.cs:37

  • Couchbase.Lite.Support

ThreadSafety.DoLockedBridge (LiteCore.Interop.C4TryLogicDelegate2 a) C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\Couchbase.Lite.Shared\Support\ThreadSafety.cs:72

  • Couchbase.Lite.Internal.Query

XQuery.Execute () C:\Jenkins\workspace\couchbase-lite-net-edition-build\couchbase-lite-net-ee\couchbase-lite-net\src\Couchbase.Lite.Shared\Query\XQuery.cs:78

  • TopSpecInterface.ServiceModel

ContactEntry.GetContactListByString2 () /Volumes/Untitled/Top_Spec/DbExtensionClasses.cs:1788

Are you using index(es)? What is your query look like? Can you Explain() your query?

Yes - I am using indexes - I have a basic index on type and postcode in this case,
It a basically a table of contacts that I iterate to add on to a map. var count = 0;

Code example - I have simplified it a bit.

var AllContactsMain = new List();
var i = 0;
bool haserrored = false;
int batchamount = 10000;
do
{
try {
using (var query = QueryBuilder.Select(SelectResult.Expression(Meta.ID), SelectResult.Expression(Meta.Sequence), SelectResult.Property(“id”), SelectResult.Property(“types”), SelectResult.Property(“lastname”), SelectResult.Property(“companyName”), SelectResult.Property(“postcode”)).From(DataSource.Database(Datab.db))
.Where(Expression.Property(“type”).EqualTo(Expression.String(“ContactEntry”))
).Limit(Expression.Int(batchamount), Expression.Int(i)))
{
count = 0;
foreach (var result in query.Execute())
{
var Id = result.GetString(“id”);
var seq = result.GetLong(1);
var Types = result.GetArray(“types”).ToList();
var CompanyName = result.GetString(“companyName”);
var Lastname = result.GetString(“lastname”);
var Postcode = result.GetString(“postcode”);
bool EndUser = Types.Contains(“End User”);
bool Yard = Types.Contains(“Yard”);
bool Retailer = Types.Contains(“Retailer”);
bool Wholesaler = Types.Contains(“Distributor”);
bool Vet = Types.Contains(“Vet”);
AllContactsMain.Add(new ContactStub { Sequence = seq , Id = Id, EndUser = EndUser, Yard = Yard, Retailer = Retailer, Vet = Vet, Wholesaler = Wholesaler });
count = count + 1;
}

                }
            }
            catch (Exception ex)
            {
                Crashes.TrackError(ex);
                count = 0;
                haserrored = true;
            }
            i = i + batchamount ;
        } while (count == batchamount );

Explain() Output is as follows

SELECT fl_result(_doc.key), fl_result(_doc.sequence), fl_result(fl_value(_doc.body, ‘id’)), fl_result(fl_value(_doc.body, ‘types’)), fl_result(fl_value(_doc.body, ‘lastname’)), fl_result(fl_value(_doc.body, ‘companyName’)), fl_result(fl_value(_doc.body, ‘postcode’)) FROM kv_default AS _doc WHERE (fl_value(_doc.body, ‘type’) = ‘ContactEntry’) AND (_doc.flags & 1 = 0) LIMIT MAX(0, 10000) OFFSET MAX(0, 0)

19|0|0| SEARCH TABLE kv_default AS _doc USING INDEX contactE4 (=?)

{“WHERE”:["=",[".type"],“ContactEntry”],“LIMIT”:10000,“OFFSET”:0,“WHAT”:[["._id"],["._sequence"],[".id"],[".types"],[".lastname"],[".companyName"],[".postcode"]]}

Index is as follows

     Datab.db.CreateIndex("contactE4", Couchbase.Lite.Query.IndexBuilder.ValueIndex(new[] { Couchbase.Lite.Query.ValueIndexItem.Property("type"), Couchbase.Lite.Query.ValueIndexItem.Property("postcode") }));

Thanks @peterknowles There is nothing out of ordinary in your query, index and code. The only suggestion is try to use Expression.Parameter in the QueryBuilder and reuse QueryBuilder object since it’s expensive to create.

Corrupt Revision Data - unable to parse the deceived fleece data in the document
We need to get the content of the document.

In order to identify the problem document, which will take some effort on your end. Please try this:
Run the query offset 190000 limit 1, if that works use limit 2, 3, 4, etc until it fails (Or some system whereby you identify that it is row #19xxxx). Then run the query with just the ID to find the ID of the document at row 19xxxx.