                 removeSchemeTask(urlSchemeTask: urlSchemeTask)
                 return
             }
-            DispatchQueue.global(qos: .userInitiated).async {
+            // IMPORTANT: Ensure the urlSchemeTask is not strongly captured by this block operation
+            // Otherwise it will sometimes be deallocated on a non-main thread, causing a crash https://phabricator.wikimedia.org/T224113
+            let op = BlockOperation { [weak urlSchemeTask] in
                 if let cachedResponse = self.defaultHandler.cachedResponseForURL(defaultURL) {
                     DispatchQueue.main.async {
+                        guard let urlSchemeTask = urlSchemeTask else {
+                            return
+                        }
+                        self.activeCacheOperations.removeValue(forKey: urlSchemeTask.request)
                         urlSchemeTask.didReceive(cachedResponse.response)
                         urlSchemeTask.didReceive(cachedResponse.data)
                         urlSchemeTask.didFinish()

        guard schemeTaskIsActive(urlSchemeTask: urlSchemeTask) else {
            return
        }
        
        let callback = Session.Callback(response: {  response in
            DispatchQueue.main.async {
                guard self.schemeTaskIsActive(urlSchemeTask: urlSchemeTask) else {
                    return
                }

    @objc let scheme: String
    private let session: Session
    private var activeSessionTasks: [URLRequest: URLSessionTask] = [:]
    private var activeCacheOperations: [URLRequest: Operation] = [:]
    private var activeSchemeTasks = NSMutableSet(array: [])
    
    private let cache: SchemeHandlerCache
