Errors

Last updated 4 months ago

Error Reporting

Swift
Objective-C
Java
Javascript
.Net

Certain sync-related APIs perform asynchronous operations that may fail. These APIs take completion blocks which accept an error parameter; if the error parameter is passed in the operation failed. The error can be checked for more detail.

It is strongly recommended to also set an error handler on the SyncManager singleton. Errors involving the global synchronization subsystem or specific sessions (which represent Realms opened for synchronization with the server) will be reported through this error handler. When errors occur, the error handler will be called with an object representing the error, as well as a SyncSession object representing the session the error occurred on (if applicable).

SyncManager.shared.errorHandler = { error, session in
// handle error
}

Realm Platform errors are represented by SyncError values, which conform to Swift’s Errorprotocol.

Certain sync-related APIs perform asynchronous operations that may fail. These APIs take completion blocks which accept an error parameter; if the error parameter is passed in the operation failed. The error can be checked for more detail.

It is strongly recommended to also set an error handler on the RLMSyncManager singleton. Errors involving the global synchronization subsystem or specific sessions (which represent Realms opened for synchronization with the server) will be reported through this error handler. When errors occur, the error handler will be called with an object representing the error, as well as a RLMSyncSession object representing the session the error occurred on (if applicable).

[[RLMSyncManager sharedManager] setErrorHandler:^(NSError *error, RLMSyncSession *session) {
// handle error
}];

Realm Mobile Platform errors are represented by NSError objects whose domain is RLMSyncErrorDomain. Please consult the definitions of RLMSyncError and RLMSyncAuthError for error codes and what they mean.

It is possible to set up error handling by registering an error handler:

SyncConfiguration configuration = new SyncConfigurtion.Builder(user, serverURL)
.errorHandler(new Session.ErrorHandler() {
void onError(Session session, ObjectServerError error) {
// do some error handling
}
})
.build();

It is also possible to register a default global error handler that will apply to all SyncConfigurations:

SyncManager.setDefaultSessionErrorHandler(myErrorHandler);

The error handling is set up by registering a callback (error) as part of the configuration:

const config = {
sync: {
user: userA,
url: realmUrl,
error: (error) => {
console.log(error.name, error.message);
},
},
schema: [{ name: 'Dog', properties: { name: 'string' } }]
};
var realm = new Realm(config);

Realm Platform errors are represented by SessionExceptions. In addition to the standard exception properties, you have access to an ErrorCode that contains information about the type of the error and allows you to have strongly typed handling logic, e.g.:

Session.Error += (session, errorArgs) =>
{
var sessionException = (SessionException)errorArgs.Exception;
switch (sessionException.ErrorCode)
{
case ErrorCode.AccessTokenExpired:
case ErrorCode.BadUserAuthentication:
// Ask user for credentials
break;
case ErrorCode.PermissionDenied:
// Tell the user they don't have permissions to work with that Realm
break;
case ErrorCode.Unknown:
// Likely the app version is too old, prompt for update
break;
// ...
}
};

Setting the client logging level

While developing your application, you will likely need to troubleshoot unexpected behavior. When doing this, it is useful to increase the Realm logging level within your application.

Swift
Objective-C
Java
Javascript
.Net

The synchronization subsystem supports a number of logging levels, useful while developing an app. These can be selected by setting the logLevel property on the SyncManager singleton to the desired verbosity:

SyncManager.shared.logLevel = .debug

The logging level must be set before any synced Realms are opened. Changing it after the first synced Realm is opened will have no effect.

The synchronization subsystem supports a number of logging levels, useful while developing an app. These can be selected by setting the logLevel property on the RLMSyncManager singleton to the desired verbosity:

[[RLMSyncManager sharedManager] setLogLevel:RLMSyncLogLevelDebug];

The logging level must be set before any synced Realms are opened. Changing it after the first synced Realm is opened will have no effect.

By enabling more verbose logs, you can better see what is happening through Android logcat.

RealmLog.setLevel(Log.DEBUG);

These can be selected by setting the logLevel property on Realm.sync to the desired verbosity. For example:

Realm.Sync.setLogLevel("debug");

The LogLevel is a static property on the SyncConfiguration class

It can be set like so:

configuration.LogLevel = debug;

Available levels are as follows:

  • fatal

  • error

  • warn

  • info

  • detail

  • debug

  • trace

Errors

Client Reset

Swift
Objective-C
Java
Javascript
.Net

If a Realm Object Server crashes and must be restored from a backup, there is a possibility that an app might need to carry out a client reset on a given synced Realm. This will happen if the local version of the Realm in question is greater than the version of that same Realm on the server (for example, if the application made changes after the Realm Object Server was backed up, but those changes weren’t synced back to the server before it crashed and had to be restored).

The client reset procedure is as follows: a backup copy of the local Realm file is made, and then the Realm files are deleted. The next time the app connects to the Realm Object Server and opens that Realm, a fresh copy will be downloaded. Changes that were made after the Realm Object Server was backed up but weren’t synced back to the server will be preserved in the backup copy of the Realm, but will not be present when the Realm is re-downloaded.

The need for a client reset is indicated by an error sent to the SyncManager error handler. This error will be denoted by the code .clientResetError.

The error object will also contain two values: the location of the backup copy of the Realm file once the client reset process is carried out, and a token object which can be passed into the SyncSession.immediatelyHandleError(_:) method to manually initiate the client reset process.

If the client reset process is manually initiated, all instances of the Realm in question must first be invalidated and destroyed. Note that a Realm might not be fully invalidated, even if all references to it are nil’ed out, until the autorelease pool containing it is drained. However, doing so allows the Realm to be immediately re-opened after the client reset process is complete, allowing syncing to resume.

If the client reset process is not manually initiated, it will instead automatically take place after the next time the app is launched, upon first accessing the SyncManager singleton. It is the app’s responsibility to persist the location of the backup copy if needed, so that the backup copy can be found later.

A Realm which needs to be reset can still be written to and read from, but no subsequent changes will be synced to the server until the client reset is complete and the Realm is re-downloaded. It is extremely important that your application listen for client reset errors and, at the very least, make provisions to save user data created or modified after a client reset is triggered so it can later be written back to the re-downloaded copy of the Realm.

The backup copy file path and reset initiation token can be obtained by calling SyncError.clientResetInfo() on the error object.

The following example shows how the client reset APIs might be used to carry out a client reset:

SyncManager.shared.errorHandler = { error, session in
let syncError = error as! SyncError
switch syncError.code {
case .clientResetError:
if let (path, clientResetToken) = syncError.clientResetInfo() {
closeRealmSafely()
saveBackupRealmPath(path)
SyncSession.immediatelyHandleError(clientResetToken)
}
default:
// Handle other errors...
()
}
}

If a Realm Object Server crashes and must be restored from a backup, there is a possibility that an app might need to carry out a client reset on a given synced Realm. This will happen if the local version of the Realm in question is greater than the version of that same Realm on the server (for example, if the application made changes after the Realm Object Server was backed up, but those changes weren’t synced back to the server before it crashed and had to be restored).

The client reset procedure is as follows: a backup copy of the local Realm file is made, and then the Realm files are deleted. The next time the app connects to the Realm Object Server and opens that Realm, a fresh copy will be downloaded. Changes that were made after the Realm Object Server was backed up but weren’t synced back to the server will be preserved in the backup copy of the Realm, but will not be present when the Realm is re-downloaded.

The need for a client reset is indicated by an error sent to the RLMSyncManager error handler. This error will be denoted by the code RLMSyncErrorClientResetError.

The error object will also contain two values: the location of the backup copy of the Realm file once the client reset process is carried out, and a token object which can be passed into the +[RLMSyncSession immediatelyHandleError:] method to manually initiate the client reset process.

If the client reset process is manually initiated, all instances of the Realm in question must first be invalidated and destroyed. Note that a RLMRealm might not be fully invalidated, even if all references to it are nil’ed out, until the autorelease pool containing it is drained. However, doing so allows the Realm to be immediately re-opened after the client reset process is complete, allowing syncing to resume.

If the client reset process is not manually initiated, it will instead automatically take place after the next time the app is launched, upon first accessing the RLMSyncManager singleton. It is the app’s responsibility to persist the location of the backup copy if needed, so that the backup copy can be found later.

A Realm which needs to be reset can still be written to and read from, but no subsequent changes will be synced to the server until the client reset is complete and the Realm is re-downloaded. It is extremely important that your application listen for client reset errors and, at the very least, make provisions to save user data created or modified after a client reset is triggered so it can later be written back to the re-downloaded copy of the Realm.

The backup copy file path can be obtained by calling -[NSError rlmSync_clientResetBackedUpRealmPath]upon the NSError object. It can also be extracted directly from the userInfo dictionary using the kRLMSyncPathOfRealmBackupCopyKey key.

The reset initiation token can be obtained by calling -[NSError rlmSync_errorActionToken] upon the NSError object. It can also be extracted directly from the userInfo dictionary using the kRLMSyncErrorActionTokenKey key.

The following example shows how the client reset APIs might be used to carry out a client reset:

[[RLMSyncManager sharedManager] setErrorHandler:^(NSError *error, RLMSyncSession *session) {
if (error.code == RLMSyncErrorClientResetError) {
[realmManager closeRealmSafely];
[realmManager saveBackupRealmPath:[error rlmSync_clientResetBackedUpRealmPath]];
[RLMSyncSession immediatelyHandleError:[error rlmSync_errorActionToken]];
return;
}
// Handle other errors...
}];

Details coming soon!

If a Realm Object Server crashes and must be restored from a backup, there is a possibility that an app might need to carry out a client reset on a given synced Realm. This will happen if the local version of the Realm in question is greater than the version of that same Realm on the server (for example, if the application made changes after the Realm Object Server was backed up, but those changes weren’t synced back to the server before it crashed and had to be restored).

The client reset procedure is as follows: a backup copy of the local Realm file is made, and then the Realm files are deleted. The next time the app connects to the Realm Object Server and opens that Realm, a fresh copy will be downloaded. Changes that were made after the Realm Object Server was backed up but weren’t synced back to the server will be preserved in the backup copy of the Realm, but will not be present when the Realm is re-downloaded.

The need for a client reset is indicated by an error sent to the registered error handler. The property name will be ClientReset.

The error object will also contain two values: the location of the backup copy of the Realm file once the client reset process is carried out, and a token object which can be passed into the Realm.Sync.initiateClientReset method to manually initiate the client reset process.

If the client reset process is manually initiated, all instances of the Realm in question must first be invalidated and destroyed. Note that a Realm might not be fully invalidated, even if all references to it are nil’ed out, until the autorelease pool containing it is drained. However, doing so allows the Realm to be immediately re-opened after the client reset process is complete, allowing syncing to resume.

If the client reset process is not manually initiated, it will instead automatically take place after the next time the app is launched. It is the app’s responsibility to persist the location of the backup copy if needed, so that the backup copy can be found later.

A Realm which needs to be reset can still be written to and read from, but no subsequent changes will be synced to the server until the client reset is complete and the Realm is re-downloaded. It is extremely important that your application listen for client reset errors and, at the very least, make provisions to save user data created or modified after a client reset is triggered so it can later be written back to the re-downloaded copy of the Realm.

The following example shows how the client reset APIs might be used to carry out a client reset:

config.sync.error = (error) => {
if (error.name === 'ClientReset') {
const path = realm.path;
realm.close();
Realm.Sync.initializeClientReset(path);
// copy required objects from Realm at error.config.path
}
};

If a Realm Object Server crashes and must be restored from a backup, there is a possibility that an app might need to carry out a client reset on a given synced Realm. This will happen if the local version of the Realm in question is greater than the version of that same Realm on the server (for example, if the application made changes after the Realm Object Server was backed up, but those changes weren’t synced back to the server before it crashed and had to be restored).

The client reset procedure is as follows: a backup copy of the local Realm file is made, and then the Realm files are deleted. The next time the app connects to the Realm Object Server and opens that Realm, a fresh copy will be downloaded. Changes that were made after the Realm Object Server was backed up but weren’t synced back to the server will be preserved in the backup copy of the Realm, but will not be present when the Realm is re-downloaded.

The need for a client reset is indicated by an error sent to Session.Error subscribers. You can check the error type by examining the result of sessionException.ErrorCode.IsClientResetError or safe-casting the exception to ClientResetException. This type contains an additional property - BackupFilePath - that contains the location of the backup copy of the Realm file once the client reset process is carried out, as well as a method - InitiateClientReset which can be called to initiate the client reset process.

If the method is called to manually initiate the client reset process, all instances of the Realm in question must first be closed by calling Dispose() before the method is invoked. However, doing so allows the Realm to be immediately re-opened after the client reset process is complete, allowing syncing to resume.

If InitiateClientReset is not called, the client reset process will automatically take place after the next time the app is launched, upon first obtaining a Realm instance. It is the app’s responsibility to persist the location of the backup copy if needed, so that the backup copy can be found later.

A Realm which needs to be reset can still be written to and read from, but no subsequent changes will be synced to the server until the client reset is complete and the Realm is re-downloaded. It is extremely important that your application listen for client reset errors and, at the very least, make provisions to save user data created or modified after a client reset is triggered so it can later be written back to the re-downloaded copy of the Realm.

The following example shows how the client reset APIs might be used to carry out a client reset:

void CloseRealmSafely()
{
// Safely dispose the realm instances, possibly notify the user
}
void SaveBackupRealmPath(string path)
{
// Persist the location of the backup realm
}
void SetupErrorHandling()
{
Session.Error += (session, errorArgs)
{
var sessionException = (SessionException)errorArgs.Exception;
if (sessionException.ErrorCode.IsClientResetError())
{
var clientResetException = (ClientResetException)errorArgs.Exception;
CloseRealmSafely();
SaveBackupRealmPath(clientResetException.BackupFilePath);
clientResetException.InitiateClientReset();
}
// Handle other errors
}
}

Permission Denied

Swift
Objective-C
Java
Javascript
. Net

If a user attempts to perform operations on a Realm for which they do not have appropriate permissions, a permission denied error will be reported. Such an error may occur, for example, if a user attempts to write to a Realm for which they only have read permissions or opens a Realm for which they have no permissions at all.

It is important to note that if a user has only read access to a particular synchronized Realm they must open that Realm asynchronously using the Realm.asyncOpen(configuration:, callbackQueue:, callback:)API. Failure to do so will lead to a permission denied error being reported.

A permission denied error will be denoted by the code .permissionDeniedError. The error object will contain an opaque token which can be used to delete the offending Realm file. The token can be obtained by calling SyncError.deleteRealmUserInfo() on the error object.

In all cases, a permission denied error indicates that the local copy of the Realm on the user’s device has diverged in a way that cannot be reconciled with the server. The file will be automatically deleted the next time the application is launched. The token included with the error can also be passed into the SyncSession.immediatelyHandleError(_:) method in order to immediately delete the Realm files.

If the token is used to immediately delete the Realm files, all instances of the Realm in question must first be invalidated and destroyed. Note that a Realm might not be fully invalidated, even if all references to it are nil’ed out, until the autorelease pool containing it is drained. However, doing so allows the Realm to be immediately re-opened in the correct way or after the correct permissions have been set, allowing syncing to resume.

If a user attempts to perform operations on a Realm for which they do not have appropriate permissions, a permission denied error will be reported. Such an error may occur, for example, if a user attempts to write to a Realm for which they only have read permissions or opens a Realm for which they have no permissions at all.

It is important to note that if a user has only read access to a particular synchronized Realm they must open that Realm asynchronously using the +[RLMRealm asyncOpenWithConfiguration:callbackQueue:callback:] API. Failure to do so will lead to a permission denied error being reported.

A permission denied error will be denoted by the code RLMSyncErrorPermissionDeniedError . The error object will contain an opaque token which can be used to delete the offending Realm file. The token can be obtained by calling -[NSError rlmSync_errorActionToken] upon the NSError object. It can also be extracted directly from the userInfo dictionary using the kRLMSyncErrorActionTokenKey key.

In all cases, a permission denied error indicates that the local copy of the Realm on the user’s device has diverged in a way that cannot be reconciled with the server. The file will be automatically deleted the next time the application is launched. The token included with the error can also be passed into the +[RLMSyncSession immediatelyHandleError:] method in order to immediately delete the Realm files.

If the token is used to immediately delete the Realm files, all instances of the Realm in question must first be invalidated and destroyed. Note that a RLMRealm might not be fully invalidated, even if all references to it are nil’ed out, until the autorelease pool containing it is drained. However, doing so allows the Realm to be immediately re-opened in the correct way or after the correct permissions have been set, allowing syncing to resume.

Details coming soon!

Details coming soon!

If a user attempts to perform operations on a Realm for which they do not have appropriate permissions, a permission denied error will be reported. Such an error may occur, for example, if a user attempts to write to a Realm for which they only have read permissions or opens a Realm for which they have no permissions at all.

It is important to note that if a user has only read access to a particular synchronized Realm they must open that Realm asynchronously using the Realm.GetInstanceAsync API. Failure to do so will lead to a permission denied error being reported.

A permission denied error will be denoted by the code ErrorCode.PermissionDenied and its runtime type will be PermissionDeniedException. In all cases, this error indicates that the local copy of the Realm can no longer synchronize with the remote one and will be automatically deleted the next time the application is launched. If you want to perform the deletion immediately so you can reopen the Realm, you can invoke the PermissionDeniedException.DeleteRealmUserInfo method with an argument deleteRealm: true. Be advised that all references to that Realm must be disposed of prior to invoking the method. If you want to cancel the deletion, you can pass deleteRealm: false.

Session Specific Errors

Error Message

Cause

204 “Illegal Realm path (BIND)”

Indicates that the Realm path is not valid for the user.

207 or 208 “Bad server file identifier (IDENT)”

Indicates that the local Realm specifies a link to a server-side Realm that does not exist. This is most likely because the server state has been completely reset.

211 “Diverging histories (IDENT)”

Indicates that the local Realm specifies a server version that does not exists. This is most likely because the server state has been partially reset (for example because a backup was restored).

Client Level Errors

Error Message

Cause

105 “Wrong protocol version (CLIENT)”

The client and the server use different versions of the sync protocol due to a mismatch in upgrading. For example: "client protocol version = 24, server protocol version = 22". Refer to Version Compatibilities table to ensure client and server are compatible.

108 “Client file bound in other session (IDENT)”

Indicates that multiple sync sessions for the same client-side Realm file overlap in time.

203 “Bad user authentication (BIND, REFRESH)”

Indicates that the server has produced a bad token, or that the SDK has done something wrong.

206 “Permission denied (BIND, REFRESH)”

Indicates that the user does not have permission to access the Realm at the given path.

Not what you were looking for? Leave Feedback