Troubleshooting

In the event of something going wrong while using the Kinvey iOS SDK, there are some steps you can take to figure out what the issue might be. The Kinvey iOS SDK will throw an exception when an error occurs.

Logging

The SDK comes with a logging facility that can be used to register the internal operation of the SDK. It uses different log levels to define how detailed the log information is.

Logging is enabled by default at .warning level. To change the logging level, set Kinvey.logLevel according to the table below.

Kinvey.logLevel = .debug
Log LevelDescription
.verboseLog operations that are useful if you are debugging but with additional information
.debugLogs operations that are useful if you are debugging
.infoLogs operations giving additional information for basic operations
.warningOnly logs warning messages
.errorOnly logs error messages
.severeOnly logs severe error messages
.noneDisables logging

To disable logging, set the log level to .none.

Operating on log levels .info and more verbose can affect performance negatively. Log levels .warning and more verbose are not suitable for production apps.

Normally, network requests and responses are not logged to prevent the log from filling up the available storage space. If you need to log network calls, you can enable this separately for each Client instance.

Kinvey.sharedClient.logNetworkEnabled = true

Error Handling

The Kinvey.Error enumeration conforms to the Swift.Error, LocalizedError, CustomStringConvertible, and CustomDebugStringConvertible protocols and contains a case for each possible error type in the Kinvey iOS library.

The following code reads all entities in the Book collection and comes with a separate block for handling objectIdMissing. This error is thrown when an entity object is expected to contain an entity ID but doesn't, which can happen when you forgot to include it or if a business logic layer is modifying the request or the result in a way that affects the ID. Some external data connectivity cases can also cause this error to appear.

dataStore.find() { (result: Result<AnyRandomAccessCollection<Book>, Swift.Error>) in
    switch result {
    case .success(let books):
        print("Books: \(books)")
    case .failure(let error):
        print("Error: \(error)")

        if let error = error as? Kinvey.Error {
            switch error {
            case .objectIdMissing:
                print("Handle error here")
            default:
                print("Default-sink code for all other errors")
            }
        }
    }
}

After you go into the .failure case, you need to test for the exact Kinvey error type and specify how you want to handle it. Use a switch statement with a case for each error type that you want to handle explicitly. Don't forget to include the default option that caches all other errors.

dataStore.find() { (result: Result<AnyRandomAccessCollection<Book>, Swift.Error>) in
    switch result {
    case .success(let books):
        print("Books: \(books)")
    case .failure(let error):
        print("Error: \(error)")

        if let error = error as? Kinvey.Error {
            switch error {
            case .objectIdMissing:
                print("Handle error here")
            case .methodNotAllowed(let httpResponse, let data, let debug, let description):
                if let httpResponse = httpResponse {
                    print(httpResponse)
                }
                if let data = data {
                    print(data)
                }
                print(debug)
                print(description)
            case .dataLinkEntityNotFound(let httpResponse, let data, let debug, let description):
                if let httpResponse = httpResponse {
                    print(httpResponse)
                }
                if let data = data {
                    print(data)
                }
                print(debug)
                print(description)
            default:
                print("Default-sink code for all other errors")
            }
        }
    }
}

While some Kinvey errors like objectIdMissing are simple strings containing the error message, others provide extended information that you can use in the handler. The following example demonstrates a few of these error types and the data they carry. As with any Swift enumeration, you can access the variables directly under the case.

dataStore.find(query, options: nil) { (result: Result<AnyRandomAccessCollection<Book>, Swift.Error>) in
    switch result {
    case .success(let items):
        print(items)
    case .failure(let error):
        if let error = error as? Kinvey.Error {
            switch error {
            case .unauthorized(let httpResponse, let data, let errorMessage, let debugMessage, let description):
                print(httpResponse?.statusCode as Any) // 401
                print(data!) // 209 bytes
                print(errorMessage) // InsufficientCredentials
                print(debugMessage)
                // The credentials used to authenticate this request are not
                // authorized to run this operation. Please retry your request
                // with appropriate credentials.
                print(description)
            case .unknownJsonError(let httpResponse, let data, let jsonObject):
                print(httpResponse?.statusCode as Any) // 400
                print(data!) // 274 bytes
                // ["debug": The script was terminated due to timing constraints:
                // took more than 2000ms to complete. Did you forget to call
                // response.complete() or response.continue()?, "description":
                // The Business Logic script did not complete. Please contact
                // support, "error": BLTimeoutError]
                print(jsonObject)
            case .invalidResponse(let httpResponse, _):
                print(error) // Invalid response from the server
                print(httpResponse?.statusCode as Any) // 400
            default:
                print(error)
            }
        }
    }
}

Error Reporting

All Kinvey REST APIs return error responses using standard HTTP error codes. The error reporting is designed to make the APIs more usable—easy to implement and debug. Starting with API version 1, error responses are consistent across all REST API endpoints and use a structured format.

Not all errors make sense when accessing Kinvey using the iOS library. Because of that, the library does not wrap the full list of REST API errors.

Every error response uses a universal dictionary to describe the error. The dictionary may see some updates from time to time but any updates are only expected to add new types of errors. Individual REST API methods will describe any behavior that diverges from the dictionary.

ErrorStatusCodeDescription
ParameterValueOutOfRange400The value specified for one of the request parameters is out of range
InvalidQuerySyntax400The query string in the request has an invalid syntax
MissingQuery400The request is missing a query string
JSONParseError400Unable to parse the JSON in the request
MissingRequestHeader400The request is missing a required header
IncompleteRequestBody400The request body is either missing or incomplete
MissingRequestParameter400A required parameter is missing from the request
InvalidIdentifier400One of more identifier names in the request has an invalid format
FeatureUnavailable400Requested functionality is unavailable in this API version
CORSDisabled400Cross Origin Support is disabled for this application
APIVersionNotAvailable400This API version is not available for your app. Please retry your request with a supported API version
BadRequest400Unable to understand request
BLRuntimeError400The Business Logic script has a runtime error. See debug message for details
InvalidCredentials401Invalid credentials. Please retry your request with correct credentials
InsufficientCredentials401The credentials used to authenticate this request are not authorized to run this operation. Please retry your request with appropriate credentials
WritesToCollectionDisallowed403This collection is configured to disallow any modifications to an existing entity or creation of new entities
IndirectCollectionAccessDisallowed403Please use the appropriate API to access this collection for this app backend
AppProblem403There is a problem with this app backend that prevents execution of this operation. Please contact support@kinvey.com for assistance
EntityNotFound404This entity not found in the collection
CollectionNotFound404This collection not found for this app backend
AppNotFound404This app backend not found
UserNotFound404This user does not exist for this app backend
BlobNotFound404This blob not found for this app backend
UserAlreadyExists409This username is already taken. Please retry your request with a different username
StaleRequest409The time window for this request has expired
KinveyInternalErrorRetry500The Kinvey server encountered an unexpected error. Please retry your request
KinveyInternalErrorStop500The Kinvey server encountered an unexpected error. Please contact support@kinvey.com for assistance
DuplicateEndUsers500More than one user registered with this username for this application. Please contact support@kinvey.com for assistance
APIVersionNotImplemented501This API version is not implemented. Please retry your request with a supported API version
APIVersionNotAvailable501This API version is not available for your app. Please retry your request with a supported API version
BLSyntaxError550The Business Logic script has a syntax error(s). See debug message for details
BLTimeoutError 550The Business Logic script did not complete in time. See debug message for details
BLViolationError550The Business Logic script violated a constraint. See debug message for details
BLInternalError550The Business Logic script did not complete. See debug message for details

The body of the response contains information on the error. The body is JSON formatted like regular responses. Errors are guaranteed to remain unchanged when using a specific API version. Each error response body contains an HTTP response Status Code and up to three attributes: two mandatory and one optional, as described below.

  • The error attribute is always present. It contains a String value representing the error type.
  • The StatusCode is the HTTP response code associated with the error.
  • The description attribute is always present. It contains a short user-friendly description of the error. You can pass the description up to the application user if you desire. Kinvey deserves the right to change the exact text of a description depending on developer feedback.
  • The debug attribute is optional and exists solely to help debug the error. An app may choose to log this debug message if the application is running in debug mode. The Kinvey backend may or may not populate this attribute depending on the exact scenario encountered. The goal with this attribute is to provide useful information that will make it very easy to isolate the root cause and implement a fix.

Support Forums

The Kinvey support forums contain valuable information and especially help with specific scenarios that may be closely related to the issues you are experiencing.

If none of the existing topics answers your question, you are welcome to post it as a new topic and one of our engineers will point in you in the right direction.