Search code examples
iosswiftcloudkitckqueryoperation

CKError: Query filter exceeds the limit of values: 250 for container


I want to pull down around 500 "Visit" records from the public database. CloudKit only gives you 100 records at a time so I just utilize the CKQueryCursor like below to get all the records I want.

func fetchVisits(_ cursor: CKQueryCursor? = nil) {
    print("fetchVisits \(cursor)")
    var operation: CKQueryOperation!
    if let cursor = cursor {
        operation = CKQueryOperation(cursor: cursor)
    } else {
        let query = CKQuery(recordType: "Visit", predicate: NSPredicate(format: "Client IN %@ AND ANY Students IN %@", visitClients, visitStudents))
        operation = CKQueryOperation(query: query)
    }
    operation.recordFetchedBlock = {
        (record) in
        totalVisits.append(record)
    }
    operation.queryCompletionBlock = {
        (cursor, error) in
        if let error = error {
            //handle error
        } else if let cursor = cursor {
            self.fetchVisits(cursor)
        } else {
            //all done!
        }
    }
    CKContainer.default().publicCloudDatabase.add(operation)
}

I call the function like:

fetchVisits()

That works fine, it gets all the visits I need. Console Log

fetchVisits nil
fetchVisits Optional(<CKQueryCursor: 0x174228140; id=4bb7887c326fc719, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x17422a320; id=f67fb25669486da9, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x174228380; id=7e87eb8b7cfe1a74, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x17422cc80; id=e77e47ef2b29c8a4, zone=(null)>)

But the issue is now I want to refresh when I push a button and now it gives me this error:

"Service Unavailable" (6/2022); "Request failed with http status code 503"; Retry after 30.0 seconds

Which is pretty self explanatory, I guess I am overwhelming the server by requesting a measly 500 records? So I wait 30 seconds and invoke the function again and now I get this error.

"Limit Exceeded" (27/2023); server message = "Query filter exceeds the limit of values: 250 for container

For some reason I cannot run that function again. If I restart the app it works fine again but only the first time. This issue seems to be specific to any table that returns a CKQueryCursor. I have other tables that I'm hitting that have less than 100 records (so the cursor is nil) and I can pull those multiple times without any issues.


Solution

  • Ok, so I've seen this before and the issue is, I believe, a bug in on the CloudKit servers. In my experience, it has to do with complex queries.

    If you try changing your predicate to:

    NSPredicate(value: true)
    

    Or even simplifying your existing one by removing the ANY part, that may be enough to fix it.