Sync Gateway log: "setCheckpoint --> 409 Document update conflict"

I’m using Sync Gateway 2.6, CB Lite .Net 2.5.3 on Windows UWP

In the Sync Gateway log I see many info lines like this:
2019-10-22T20:36:22.697+02:00 [INF] SyncMsg: c:[789a1896] #7: Type:setCheckpoint --> 409 Document update conflict Time:449.237µs

At this time the app is running a push and a pull replication in parallel (not a PushAndPull replication).
Does the error indicate an update conflict when the checkpoint is saved ?
That shouldn’t happen, right ?
Or does the message indicate something else ?

I reviewed Document update conflict, it talks about the same log message, but I don’t understand @Jens response.

This is a conflict from a CBL replicator storing a checkpoint on the server. It’s not a document conflict in the usual sense.

This shouldn’t happen … does your client run multiple replicators at once with the same settings?

The app is running a Push and separately a Pull replication. Both are running at the same time, but that should be OK, because push and pull replicators use separate checkpoint docs, right ?

What is the configuration settings of the push and pull replicators ?

ReplicationConfiguration{
ReplicatorType = ReplicatorType.Push,
Continuous = false,
Authenticator = …,
PushFilter = (doc, flags) => DefaultPushFilter(doc?.ToDictionary(), IsDocFlagDeleted(flags)),
PullFilter = (doc, flags) => NoFilter(doc?.ToDictionary(), IsDocFlagDeleted(flags))
}

ReplicationConfiguration{
ReplicatorType = ReplicatorType.Pull,
Continuous = false,
Authenticator = …,
PushFilter = (doc, flags) => DefaultPushFilter(doc?.ToDictionary(), IsDocFlagDeleted(flags)),
PullFilter = (doc, flags) => NoFilter(doc?.ToDictionary(), IsDocFlagDeleted(flags))
}

private bool DefaultPushFilter(IDictionary<string, object> dict, bool isDeleted)
{
  if (isDeleted)
    return true;
  if (!dict.TryGetValue(nameof(IModelEntity.ReplicationType), out var dirObj))
    return false;
  if (!Enum.TryParse(dirObj.ToString(), out ReplicationDirection dir))
    return false;
  return dir == ReplicationDirection.Push 
              || dir == ReplicationDirection.PushPull 
              || dir == ReplicationDirection.PushThenPurge;
}

private bool NoFilter(IDictionary<string, object> dict, bool isDeleted) => true;

This may be a bug. I’ll have to check, but a separate push and pull replication may get the same checkpoint ID, which would explain the problem. If that’s true, I’ll file a bug report.

The CBL 2 replication protocol can push and pull over a single socket. So it’s assumed that you will run a single push/pull replication, rather than two replications. Is there a reason you need to run these separately? If not, you can fix the problem by switching to a single replicator.

Yup, this is a bug. I filed https://issues.couchbase.com/browse/CBL-501.

The design of our app framework originated when PushAndPull was not yet available.
I’ll explore making the switch from ‘Push and Pull separately’ to ‘PushAndPull’.
Thank you.

The design of our app framework originated when PushAndPull was not yet available.

Ah…from the 1.x days ? Because PushAndPull was available from day 1 on 2.x andit is the default mode if one isn’t specified.