cloudkitckerrorckfetchnotificationchange

CloudKit Error: Change Token Expired, Reset Needed


Swift 3.1, Xcode 8.3.3

I keep getting an error from CloudKit and I don't know what to do about it.

I'm tracking notifications from CloudKit like this:

let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: previousChangeToken)

//Hold the notification IDs we processed so we can tell CloudKit to never send them to us again
var notificationIDs = [CKNotificationID]()

operation.notificationChangedBlock = { [weak self] notification in
  guard let notification = notification as? CKQueryNotification else { return }
  if let id = notification.notificationID {
    notificationIDs.append(id)
  }
}

operation.fetchNotificationChangesCompletionBlock = { [weak self] newToken, error in
  if let error = error{
    print(error) //<-- <!> This is the error <!>
  }else{
    self?.previousChangeToken = newToken

    //All records are in, now save the data locally
    let fetchOperation = CKFetchRecordsOperation(recordIDs: recordIDs)

    fetchOperation.fetchRecordsCompletionBlock = { [weak self] records, error in
      if let e = error {
        print("fetchRecordsCompletionBlock Error fetching: \(e)")
      }
      //Save records to local persistence...
    }

    self?.privateDB.add(fetchOperation)

    //Tell CloudKit we've read the notifications
    let operationRead = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDs)
    self?.container.add(operationRead)
  }
}

container.add(operation)

And the error says:

<CKError 0x174241e90: "Change Token Expired" (21/1016); server message = "Error code: RESET_NEEDED"; uuid = ...; container ID = "...">

The CKServerChangeToken documentation don't mention anything about resetting the token, and the CloudKit dashboard doesn't offer any such option.

Any idea what I'm supposed to do?


Solution

  • This error code is CKErrorCodeChangeTokenExpired, and it's an indication that you need to re-sync your changes.

    https://developer.apple.com/documentation/cloudkit/ckerror/2325216-changetokenexpired

    This error code gets returned when the change token is too old, or the container has been reset (resetting the container invalidates old change tokens).

    The comments related to this error code include:

    (Describing the code itself):

    The previousServerChangeToken value is too old and the client must re-sync from scratch

    (On various fetch operation completion/updated blocks):

    If the server returns a CKErrorChangeTokenExpired error, the serverChangeToken used for this record zone when initting this operation was too old and the client should toss its local cache and re-fetch the changes in this record zone starting with a nil serverChangeToken.