Silence Alamofire 999 Error Handling

Hi,

I'm currently working on a project in which the user can cancel a dataTask using getTasksWithCompletionHandler. However, once the task is cancelled, and before my .failure(error) closure is hit, a long error message:

Task <AF138493-B064-4F45-BB0B-80C696BBC345>.<1> load failed with error Error 
Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo= . 
{NSErrorFailingURLStringKey="SensitiveURLHere"

Is there a way I can silence this warning or handle it myself as I do not wish for the sensitive URL to be logged in full.

This isn't an Alamofire feature but logging from the underlying URLSession. Have you checked what this message looks like on device in release mode? It's possible that it cuts more of the sensitive information there. If it still shows the URL I don't think there's much you can do, as the system os_log messages aren't under developer control. There's a runtime flag you can set to turn them off (OS_ACTIVITY_MODE=disable), but it's only available in debug mode since it's a runtime flag, and it disables all os functionality, including logging, signposts, and exception printing, so it's actually better to leave it enabled for development. I would check on device in release mode before worrying about it.

Additionally, you really shouldn't use getTasksWithCompletionHandler when using Alamofire, as cancelling or otherwise modifying URLSessionTasks out from under Alamofire can lead to unexpected behavior. If there's a particular use case for seeing all active tasks, feel free to file a feature request with details, or discuss it in a thread here. I did add cancelAllRequests to Session for Alamofire 5 RC1, so if that's what it's needed for, there's now a solution. In the end, those log messages will still print, at least in debug mode.

Looking at my own Console logs, I can see that URLSession logging in release mode (i.e. on the system) considers the URLs to be private, so I don't think you need to worry:

Task <8FA33E42-3FC6-4525-A7F1-B5B25EA0A217>.<2569> finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=<private>, NSErrorFailingURLKey=<private>, _NSURLErrorRelatedURLSessionTaskErrorKey=<private>, _NSURLErrorFailingURLSessionTaskErrorKey=<private>, NSLocalizedDescription=cancelled}

2 Likes

Ah this is super helpful actually! Apologies for the non-Alamofire related question, should have investigated further.

Thanks a lot for your help

Jon,

I have a feature request related to cancellation. It would be nice to be able to selectively delete some of the active requests (instead of all of them). So perhaps we could modify cancelAllRequests to be something like this:

public func cancelAllRequests(passingTest test: (Request) -> Bool = { _ in return true},
                               completingOnQueue queue: DispatchQueue = .main,
                               completion: (() -> Void)? = nil) {
    rootQueue.async {
        self.activeRequests.filter({ test($0) }).forEach { $0.cancel() }
        queue.async { completion?() }
    }
}

So by default, the functionality would be exactly like it is now. But optionally, you could selectively pick which of the active requests you want to cancel.

That is a bit of interesting flexibility. Can I ask what your use case is more specifically?

5.0 is locked in RC at the moment, with release just waiting on us to update our advanced documentation and write a migration guide, so this wouldn't be in until 5.1 at the earliest.

So let's say you have a UIViewController which kicks off several requests. All of these requests have a particular path and HTTP method. But the user can dismiss that view controller any time they want. So if/when the user dismisses the view controller, then we want to cancel any outstanding requests. We don't want to cancel ALL requests that might be in-flight, since there might be other requests being made in other parts of the app. We only want to cancel the in-flight requests made from THAT view controller.

Sure, we could hold the DataRequest references returned by Session.request() in the view controller and then iterate through those upon viewDidDisappear or deinit. But if we had this function, then we would not need to hold those references - we could just call cancelAllRequests() with a block that selectively picked out the requests we made. Our block would just need to look at the path and HTTP method of the URLRequest and return true if it matches.

That approach also has the drawback of cancelling all loads of a resource, not just those triggered by a particular screen. Keeping the requests to cancel if necessary would be how I would do it, but I understand the request. If you want to do a PR, we can keep it around until 5.1.