Couchbase Lite Swift SDK - Replicator Ignores Public ('!') Channel?

Context

I am using the Couchbase Lite Swift SDK, version 3.2.4 and connecting to Capella via Sync Gateway. In my App Endpoint, for each linked collection I have set this access control function:

function (doc, oldDoc, meta) {channel('!');}

As I understand it, this is the public channel and the documents in the linked collection should be available to ANY user that connects to the endpoint. But the Replicator seems to ignore the public channel entirely.

If, instead, I use the default access function (where each linked collection is assigned to a channel of the same name) and then grant the user access to those channels (either via App Role or manually), the Replicator pulls down the documents perfectly.

Starting the Replicator

Here’s an excerpt of how I configure and start the Replicator. (Again, this works perfectly fine unless I try to use the public channel):

///  Configure and initiate cloud sync.
if let syncEndpointURL: URL = config.syncEndpointURL,
   let syncCredentials: SyncCredentials = config.syncCredentials
{
    let endpoint = URLEndpoint(url: syncEndpointURL)

    var config = ReplicatorConfiguration(target: endpoint)
    config.continuous = true
    config.replicatorType = .pushAndPull
    config.maxAttemptWaitTime = 10

    // `openCollections` is an array of `Collection`. I create them earlier via: 
    // `try database.createCollection(name: "foo", scope: "bar")
    config.addCollections(openCollections)
            
    switch syncCredentials
    {
    case .password(let username, let password):
        config.authenticator = BasicAuthenticator(username: username, password: password)
                
    case .oidc(let sessionID, let cookieName):
        config.authenticator = SessionAuthenticator(sessionID: sessionID, cookieName: cookieName)
    }
            
    replicator = Replicator(config: config)
    replicatorStatusToken = replicator!.addChangeListener(withQueue: parentQueue, self.handleReplicatorStatusChange(_:))            
    replicator!.start(reset: false)
 }

Another Attempted Workaround:

I even tried explicitly specifying the public channel, like this:

var collectionConfig = CollectionConfiguration()
collectionConfig.channels = ["!"]

replicatorConfig.addCollections(openCollections, config: collectionConfig)

But that still had no effect. The Replicator refuses to pull any documents from the public channel. What have I missed?

Hey! A few things to maybe check to help debug this your end:

  • When the doc is written you can check that the doc is correctly assigned the public channel in the _sync metadata by viewing the doc in the bucket and clicking metadata tab. You should see an entry under “channels” in the metadata for the channel ”!”. You can also verify the doc is being assigned the “!” channel properly through logs when the doc is written to Sync Gateway, example below:
    2025-07-21T15:31:52.253+01:00 [DBG] Changes+: db:db1 col:_default #6 ==> channels [ <ud>0.<ud>!</ud></ud> <ud>0.<ud>*</ud></ud> ]

  • You can call the _changes endpoint (Sync Gateway Public API Reference | Couchbase Docs) If you call this as the replicating user you should see the doc in question in the output. If you don’t see it in the output then the document in question probably doesn’t have the “!” channel assigned.

  • When the pull side of the replicator connects to Sync Gateway (or when you call the _changes endpoint stated above) you will get logging from the changes feed starting up on Sync Gateway. You should see something like this:
    2025-07-21T15:38:50.544+01:00 [DBG] Changes+: c:#017 db:db1 MultiChangesFeed: channels expand to "<ud>!:1,a:7,e:7</ud>" ... <ud> (to couchbase1)</ud>
    Where this tells you the channels the changes feed is looking for changes in, you can verify that the changes feed has “!:1” in this line.

If the above doesn’t help spot the problem you should repro the issue and collect logs from Sync Gateway and client so we can analyse.