5

I have an app in production that has been running fine for a while. However, since iOS 11 - I am receiving this error:

Task <51E07EF5-6F31-4E58-8818-7712CB3E49A6>.<20> HTTP load failed (error code: -999 [1:89]) Task <51E07EF5-6F31-4E58-8818-7712CB3E49A6>.<20> finished with error - code: -999

This happens on iOS 11 only. Also, it is not consistent. Out of five requests to the same URL, two will fail with this. On a Cellular connection, it happens less often, but its still there.

I am using AFNetworking and as said; this has never been an issue until iOS11.

Any ideas?

Update to add more details:

I am using SSL Pinning with valid certificates. My info.plist looks like this:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>url.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>

Using the SSL pinning like this:

    NSString *pathToProdCert = [[NSBundle mainBundle]pathForResource:@"MY_CERT" ofType:@"cer"];

if(pathToProdCert){
       manager.securityPolicy.pinnedCertificates = [NSSet setWithObjects[NSData dataWithContentsOfFile:pathToProdCert], nil];
            manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
        }

Update: In response to the comments: this is how the manager is declared:

@property (nonatomic) AFHTTPSessionManager *manager;

The manager is initialised through an init method of my web service class:

-(instancetype)initWithBaseUrl:(NSURL *)url {

    self  = [super init];
    if (self){
        self.manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
        self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    }

    return self;
}

It is only initialised once per app session.

Update: As requested this is the userInfo inside the error that comes back:

NSErrorFailingURLKey = "https://MY_URL/PARAMS"; NSErrorFailingURLStringKey = "https://MY_URL/PARAMS"; NSLocalizedDescription = cancelled; NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-999 \"(null)\" UserInfo={_kCFStreamErrorCodeKey=89, _kCFStreamErrorDomainKey=1}"; "_kCFStreamErrorCodeKey" = 89; "_kCFStreamErrorDomainKey" = 1;

Upon more testing, I have noticed that if I recreate the network class, where the manageris declared - on each network call - I never get this error.

Robert J. Clegg
  • 7,231
  • 9
  • 47
  • 99
  • Did you set up the NSAppTransportSecurity settings in the info.plist? – gotomanners Feb 06 '18 at 14:31
  • @gotomanners - Sorry, I forgot to mention that. I did, with the NSAllowsArbitraryLoads set to true. – Robert J. Clegg Feb 06 '18 at 14:38
  • Please add code how you declare manager? And how many times code for creating manager is called – Jakub Feb 14 '18 at 10:13
  • Does the request gets cancelled anyhow? See: https://developer.apple.com/documentation/foundation/1508628-url_loading_system_error_codes/nsurlerrorcancelled?language=objc – marcusficner Feb 14 '18 at 10:14
  • @marcusficner If it is, it is not my own code doing it; as I have not written code to cancel requests. Will check the link anyway - thanks. – Robert J. Clegg Feb 14 '18 at 10:22
  • Does the `NSError` object contain any more information (`userInfo`)? Can you set a breakpoint on the Task's `cancel` method so you can see from the stack trace what is going on when the Task is cancelled? – Jörn Eyrich Feb 14 '18 at 14:35
  • @JörnEyrich Added the info from the [userInfo] to the question. As for a break point on Task - where exactly should I set it? Tried to figure out where icancel is set in the library - but couldn't see what causes the cancelled. – Robert J. Clegg Feb 14 '18 at 15:12
  • Have you seen this: https://stackoverflow.com/questions/33790260/why-would-an-nsurlconnection-generate-this-error-nsposixerrordomain-operation ? (Especially the comment by the question's author.) – Phillip Mills Feb 14 '18 at 15:58
  • See here similar issue: [Error Domain=NSURLErrorDomain Code=-999 "cancelled"](https://github.com/AFNetworking/AFNetworking/issues/2895) – Krunal Feb 14 '18 at 18:23
  • It's a bug on iOS 11, on iOS 11.1 this issue is fixed. Or you can update you TLS from 1.0 to 1.2. Source: https://github.com/AFNetworking/AFNetworking/issues/3999 – bguidolim Feb 16 '18 at 16:17

3 Answers3

4

-999 or ErrorCancelled

The initialized manager is not owned, and is deallocated shortly after it goes out of scope. As a result, any pending tasks are cancelled.

Create a singleton class with AFHTTPSessionManager and use that for all your requests.

YourAPIClient.h

#import "AFHTTPSessionManager.h"
@interface YourAPIClient : AFHTTPSessionManager
+(YourAPIClient *) sharedClient;
@end

YourAPIClient.m

#import "YourAPIClient.h"

@implementation YourAPIClient

//Singleton Shared Client
+(YourAPIClient *)sharedClient
{
    static YourAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

        // Initialize Session Manager
       _sharedClient = [[YourAPIClient alloc] initWithSessionConfiguration:sessionConfiguration];
        // Configure Manager
        [_sharedClient setResponseSerializer:[AFHTTPResponseSerializer serializer]];

    });

    return _sharedClient;
}
Rukshan
  • 7,902
  • 6
  • 43
  • 61
  • This I get and it was something I explored. What I fail to understand is why is this an issue on iOS11 + devices only and not earlier versions of iOS? – Robert J. Clegg Feb 16 '18 at 12:40
1

We had a similar case. For our particular case the customers were using the app while inside a corporate network, which was injecting the company's certificates to every request. If the device doesn't have the company's custom CA, then the user would get this particular error.

Aris
  • 1,529
  • 9
  • 17
  • This isn't an issue I'm experiencing. As mentioned, we experience this issue even on a cellular network. Which rules out a company cert issue. Thanks for the input. – Robert J. Clegg Feb 16 '18 at 12:40
0

This does seem like a bug in iOS. The error code associated with the HTTP load failed(CFErrorDomainCFNetwork), 999 is for a cancelled request (cfurlErrorCancelled).

You have answered the question yourself. To get this to work on iOS 11, you should consider using a different manager for each call, as it appears that the network requests on one manager are conflicting with each other.

Reference material:

https://github.com/AFNetworking/AFNetworking/issues/3999 https://developer.apple.com/documentation/cfnetwork/cfnetworkerrors/1416998-cfurlerrorcancelled NSURLErrorDomain error code -999 in iOS

Sam
  • 649
  • 5
  • 13