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 Level | Description |
---|---|
.verbose | Log operations that are useful if you are debugging but with additional information |
.debug | Logs operations that are useful if you are debugging |
.info | Logs operations giving additional information for basic operations |
.warning | Only logs warning messages |
.error | Only logs error messages |
.severe | Only logs severe error messages |
.none | Disables logging |
To disable logging, set the log level to .none
.
.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.
Error | StatusCode | Description |
---|---|---|
ParameterValueOutOfRange | 400 | The value specified for one of the request parameters is out of range |
InvalidQuerySyntax | 400 | The query string in the request has an invalid syntax |
MissingQuery | 400 | The request is missing a query string |
JSONParseError | 400 | Unable to parse the JSON in the request |
MissingRequestHeader | 400 | The request is missing a required header |
IncompleteRequestBody | 400 | The request body is either missing or incomplete |
MissingRequestParameter | 400 | A required parameter is missing from the request |
InvalidIdentifier | 400 | One of more identifier names in the request has an invalid format |
FeatureUnavailable | 400 | Requested functionality is unavailable in this API version |
CORSDisabled | 400 | Cross Origin Support is disabled for this application |
APIVersionNotAvailable | 400 | This API version is not available for your app. Please retry your request with a supported API version |
BadRequest | 400 | Unable to understand request |
BLRuntimeError | 400 | The Business Logic script has a runtime error. See debug message for details |
InvalidCredentials | 401 | Invalid credentials. Please retry your request with correct credentials |
InsufficientCredentials | 401 | The credentials used to authenticate this request are not authorized to run this operation. Please retry your request with appropriate credentials |
WritesToCollectionDisallowed | 403 | This collection is configured to disallow any modifications to an existing entity or creation of new entities |
IndirectCollectionAccessDisallowed | 403 | Please use the appropriate API to access this collection for this app backend |
AppProblem | 403 | There is a problem with this app backend that prevents execution of this operation. Please contact support@kinvey.com for assistance |
EntityNotFound | 404 | This entity not found in the collection |
CollectionNotFound | 404 | This collection not found for this app backend |
AppNotFound | 404 | This app backend not found |
UserNotFound | 404 | This user does not exist for this app backend |
BlobNotFound | 404 | This blob not found for this app backend |
UserAlreadyExists | 409 | This username is already taken. Please retry your request with a different username |
StaleRequest | 409 | The time window for this request has expired |
KinveyInternalErrorRetry | 500 | The Kinvey server encountered an unexpected error. Please retry your request |
KinveyInternalErrorStop | 500 | The Kinvey server encountered an unexpected error. Please contact support@kinvey.com for assistance |
DuplicateEndUsers | 500 | More than one user registered with this username for this application. Please contact support@kinvey.com for assistance |
APIVersionNotImplemented | 501 | This API version is not implemented. Please retry your request with a supported API version |
APIVersionNotAvailable | 501 | This API version is not available for your app. Please retry your request with a supported API version |
BLSyntaxError | 550 | The Business Logic script has a syntax error(s). See debug message for details |
BLTimeoutError | 550 | The Business Logic script did not complete in time. See debug message for details |
BLViolationError | 550 | The Business Logic script violated a constraint. See debug message for details |
BLInternalError | 550 | The 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.