Handling Errors with the .NET SDK

Common errors and exceptions, and how to handle them.

Errors are inevitable. The developer’s job is to be prepared for whatever is likely to come up — and to try and be prepared for anything that conceivably could come up. Couchbase gives you a lot of flexibility, but it is recommended that you equip yourself with an understanding of the possibilities.

How the SDK Handles Errors

Couchbase-specific exceptions are all derived from CouchbaseException. Errors that cannot be recovered by the SDK will be returned to the application. These unrecoverable errors are left to the application developer to handle — this section covers handling many of the common error scenarios.

Handling Errors

The approach will depend upon the type of error thrown. Is it transient? Is it even recoverable? Below we examine error handling strategies in relation to the Couchbase SDKs, then take a practical walk through some common error scenarios you are likely to have to handle when working with a Couchbase cluster.

Logging

It is always important to log errors, but even more so with highly concurrent asynchronous applications.

Retry

Transient errors — such as those caused by resource starvation — are best tackled with one of the following retry strategies:

  • Retry immediately.

  • Retry with a fixed delay.

  • Retry with a linearly increasing delay.

  • Retry with an exponentially increasing delay.

  • Retry with a random delay.

async Task changeEmail()
{
		var attempts = MaxRetries; // eg 5
		while (attempts-- > 0)
		{
			  // will throw KeyNotfoundException if key doesn't exist
	  		var document = await collection.GetAsync("doc_id");
				var user = document.ContentAs<User>();
				user.Email = "john.smith@couchbase.com";

				try
				{
						await collection.ReplaceAsync("doc_id", user);

						// replace succeeded, break from loop
						break;
				}
				catch (CouchbaseException exception)
				{
						if (!exception.IsRetryable())
						{
								// unrecoverable error (network failure, etc)
								throw;
						}
				}

				// wait 100 milliseconds before trying again
				Task.Delay(100);
		}
}

KV

The KV Service exposes several common errors that can be encountered - both during development, and to be handled by the production app. Here we will cover some of the most common errors.

Key does not exist

try
{
    await collection.Replace("my-key", new { });
}
catch (KeyNotFoundException)
{
    // key does not exist
}

Key already exists

try
{
    await collection.Insert("my-key", new { });
}
catch (KeyExistsException)
{
    // key already exists
}

Document body too large

try
{
	  await collection.Insert("my-key", myReallyLargeObject);
}
catch (RequestTooBigException)
{
	  // document body is too large
}

CAS Mismatch

try
{
    var result = await collection.Get("my-key");
    await collection.Replace("my-key", new { }, options => options.WithCas(result.Cas));
}
catch (CasMismatchException)
{
    // the CAS value has changed
}