Previous Next JavaScript must be enabled to correctly display this content

## Handling Driver Errors

Learn how to handle driver-related errors and exceptions reported during building or running the application.

Java errors are thrown as exceptions when you build or run your application. The `NoSQLException` class is the base for most exceptions thrown by the driver. However, the driver throws exceptions directly for some classes, such as `IllegalArgumentException` and `NullPointerException`.

In general, NoSQL exception instances are split into two broad categories:

- Exceptions that may be retried with the expectation that they may succeed on retry.

  These exceptions are instances of the `RetryableException` class. These exceptions usually indicate resource consumption violations.

- Exceptions that will fail even after retry.

  Examples of exceptions that should not be retried are `IllegalArgumentException`, `TableNotFoundException`, and any other exception indicating a syntactic or semantic error.

Python errors are raised as exceptions defined as part of the API. They are all instances of Python’s RuntimeError. Most exceptions are instances of `borneo.NoSQLException` which is a base class for exceptions raised by the Python driver.

Exceptions are split into 2 broad categories: Exceptions that may be retried with the expectation that they may succeed on retry. These are all instances of `borneo.RetryableException`. Examples of these are the instances of `borneo.ThrottlingException` which is raised when resource consumption limits are exceeded. Exceptions that should not be retried, as they will fail again. Examples of these include `borneo.IllegalArgumentException` , `borneo.TableNotFoundException`, etc.

`borneo.ThrottlingException` instances will never be thrown in an on-premise configuration as there are no relevant limits.

Go SDK errors are reported as `nosqlerr.Error` values defined as part of the API. Errors are split into 2 broad categories:

- Errors that may be retried with the expectation that they may succeed on retry. These are retryable errors on which the `Error.Retryable()` method call returns `true`. Examples of these include `nosqlerr.OperationLimitExceeded`, `nosqlerr.ReadLimitExceeded`, `nosqlerr.WriteLimitExceeded`, which are raised when resource consumption limits are exceeded.
- Errors that should not be retried, as they will fail again. Examples of these include `nosqlerr.IllegalArgumentError`, `nosqlerr.TableNotFoundError`, etc.

Asynchronous methods of `NoSQLClient` return Promise as a result and if an error occurs it results in the Promise rejection with that error. For synchronous methods such as `NoSQLClient` constructor errors are thrown as exceptions. All errors used by the SDK are instances of `NoSQLError` or one of its subclasses. In addition to the error message, each error has `errorCode` property set to one of standard error codes defined by the ErrorCode enumeration. `errorCode` may be useful to execute conditional logic depending on the nature of the error.

For some error codes, specific subclasses of `NoSQLError` are defined, such as `NoSQLArgumentError`, `NoSQLProtocolError`, `NoSQLTimeoutError`, etc. `NoSQLAuthorizationError` may have one of several error codes depending on the cause of authorization failure. In addition, errors may have `cause` property set to the underlying error that caused the current error. Note that the cause is optional and may be an instance of an error that is not part of the SDK.

In addition, error codes are split into 2 broad categories:

- Errors that may be retried with the expectation that the operation may succeed on retry. Examples of these are `ErrorCode.READ_LIMIT_EXCEEDED` and `ErrorCode.WRITE_LIMIT_EXCEEDED` which are throttling errors (relevant for the Cloud environment), and also `ErrorCode.NETWORK_ERROR` since most network conditions are temporary.
- Errors that should not be retried, as the operation will most likely fail again. Examples of these include `ErrorCode.ILLEGAL_ARGUMENT` (represented by `NoSQLArgumentError`), `ErrorCode.TABLE_NOT_FOUND`, etc.

You can determine if the `NoSQLError` is retryable by checking `retryable` property. Its value is set to true for retryable errors and is false or undefined for non-retryable errors.

Retry Handler

The driver will automatically retry operations on a retryable error. Retry handler determines:

- Whether and how many times the operation will be retried.
- How long to wait before each retry.

RetryHandler is an interface with with 2 properties:

- `RetryHandler#doRetry` that determines whether the operation should be retried based on the operation, number of retries happened so far and the error occurred. This property is usually a function, but may be also be set to boolean false to disable automatic retries.
- `RetryHandler#delay` that determines how long to wait before each successive retry based on the same information as provided to `RetryHandler#doRetry`. This property is usually a function, but may also be set to number of milliseconds for constant delay.

NoSQLException serves as a base class for many exceptions thrown by the driver. However, in certain cases the driver uses standard exception types such as:

- `ArgumentException` and its subclasses such as `ArgumentNullException`. They are thrown when an invalid argument is passed to a method or when an invalid configuration (in code or in JSON) is passed to create NoSQLClient instance.
- `TimeoutException` is thrown when an operation issued by `NoSQLClient` has timed out. If you are getting many timeout exceptions, you may try to increase the timeout values in `NoSQLConfig` or in options argument passed to the `NoSQLClient` method.
- `InvalidOperationException` is thrown when the service is an invalid state to perform an operation. It may also be thrown if the query has failed be cause its processing exceeded the memory limit specifed in `QueryOptions.MaxMemoryMB` or `NoSQLConfig.MaxMemoryMB`. In this case, you may increase the corresponding memory limit. Otherwise, you may retry the operation.
- `InvalidCastException` and `OverflowException` may occur when working with sublcasses of FieldValue and trying to cast a value to a type it doesn't support or cast a numeric value to a smaller type causing arithmetic overflow.
- `OperationCanceledException` and `TaskCanceledException` if you issued a cancellation of the operation started by a method of `NoSQLClient` using the provided CancellationToken.

In addition, exceptions may be split into two broad categories:

- Exceptions that may be retried with the expectation that the operation may succeed on retry. In general these are subclasses of `RetryableException`. These include throttling exceptions as well as other exceptions where a resource is temporarily unavailable. Some other subclasses of `NoSQLException` may also be retryable depending on the conditions under which the exception occurred. In addition, network-related errors are retryable because most network conditions are temporary.
- Exceptions that should not be retried because they will still fail after retry. They include exceptions such as `TableNotFoundException`, `TableExistsException` and others as well as standard exceptions such as `ArgumentException`.

You can determine if a given instance of `NoSQLException` is retryable by checking its `IsRetryable` property.

Retry Handler

By default, the driver will automatically retry operations that threw a retryable exception (see above). The driver uses retry handler to control operation retries. The retry handler determines:

- Whether and how many times the operation will be retried.
- How long to wait before each retry.

All retry handlers implement `IRetryHandler` interface. This interface provides two methods, one to determine if the operation in its current state should be retried and another to determine a retry delay before the next retry. You have a choice to use default retry handler or set your own retry handler as `RetryHandler` property of `NoSQLConfig` when creating `NoSQLClient` instance.

Note:

Retries are only performed within the timeout period alloted to the operation and configured as one of timeout properties in `NoSQLConfig` or in options passed to the `NoSQLClient` method. If the operation or its retries have not succeded before the timeout is reached, `TimeoutException` is thrown.
By default, the driver uses `NoSQLRetryHandler` class which controls retires based on operation type, exception type and whether the number of retries performed has reached a preconfigured maximum. It also uses exponential backoff delay to wait between retries starting with a pre configured base delay. You may customize the properties such as maximum number of retries, base delay and others by creating your own instance of `NoSQLRetryHandler` and setting it as a `RetryHandler` property in `NoSQLConfig`. For example:

    var client = new NoSQLClient(
        new NoSQLConfig
        {
            Region = .....,
            ...............
            RetryHandler = new NoSQLRetryHandler
            {
                MaxRetryAttempts = 20,
                BaseDelay = TimeSpan.FromSeconds(2)
            }
        });

If you don't specify the retry handler, the driver will use an instance of `NoSQLRetryHandler` with default values for all parameters. Alternatively, you may choose to create your own retry handler class by implementing `IRetryHandler` interface. The last option is to disable retries all together. You may do this if you plan to retry the operations within your application instead. To disable retries, set `RetryHandler` property of `NoSQLConfig` to `NoRetries`:

    var client = new NoSQLClient(
        new NoSQLConfig
        {
            Region = .....,
            ...............
            RetryHandler = NoSQLConfig.NoRetries
        });

Handle Resource Limits: Programming in a resource-limited environment can be challenging. Tables have user-specified throughput limits and if an application exceeds those limits it may be throttled, which means an operation may fail with one of the throttling exceptions such as `ReadThrottlingException` or `WriteThrottlingException`. This is most common when using queries, which can read a lot of data, using up capacity very quickly. It can also happen for get and put operations that run in a tight loop.

Even though throttling errors will be retried and using custom `RetryHandler` may allow more direct control over retries, an application should not rely on retries to handle throttling as this will result in poor performance and inability to use all of the throughput available for the table. The better approach would be to avoid throttling entirely by rate-limiting your application. In this context rate-limiting means keeping operation rates under the limits for the table.