This guide describes the exception hierarchy and error handling patterns in the Weaviate C# client.
- Exception Hierarchy
- Common Exceptions
- Protocol-Specific Exceptions
- Error Handling Patterns
- API-Specific Behaviors
- Best Practices
Exception (System)
└── WeaviateException
├── WeaviateClientException
│ ├── WeaviateRestClientException
│ └── (other client-side errors)
└── WeaviateServerException
├── WeaviateRestServerException
├── WeaviateGrpcServerException
├── WeaviateUnexpectedStatusCodeException
├── WeaviateNotFoundException
├── WeaviateConflictException
├── WeaviateFeatureNotSupportedException
└── WeaviateBackupConflictException
Base class for all Weaviate-related exceptions.
public class WeaviateException : ExceptionWhen thrown: Never directly; serves as base for all other Weaviate exceptions.
How to handle: Catch this to handle any Weaviate-related error generically.
try
{
await client.Collections.Get("MyCollection");
}
catch (WeaviateException ex)
{
Console.WriteLine($"Weaviate error: {ex.Message}");
}Client-side errors such as invalid configuration, network issues, or serialization problems.
public class WeaviateClientException : WeaviateExceptionWhen thrown:
- Invalid client configuration
- Network connectivity issues
- Request serialization failures
- Client-side validation errors
How to handle: These typically indicate issues with your application code or environment.
try
{
var client = WeaviateClientBuilder.Local(hostname: "invalid-host").Build();
await client.IsReady();
}
catch (WeaviateClientException ex)
{
Console.WriteLine($"Client error: {ex.Message}");
// Check configuration, network connectivity, etc.
}Server-side errors returned by the Weaviate instance.
public class WeaviateServerException : WeaviateExceptionWhen thrown:
- Server returns an error response
- Server is unavailable or misconfigured
- Server-side validation failures
- Resource constraints or internal errors
How to handle: These indicate issues with the Weaviate server or your request.
try
{
await collection.Data.Insert(invalidObject);
}
catch (WeaviateServerException ex)
{
Console.WriteLine($"Server error: {ex.Message}");
// Check request validity, server logs, etc.
}Unexpected HTTP status code returned by the REST API.
internal class WeaviateUnexpectedStatusCodeException : WeaviateServerException
{
public HttpStatusCode StatusCode { get; }
public ISet<HttpStatusCode> ExpectedStatusCodes { get; }
}When thrown: REST endpoint returns a status code not in the expected set for that operation.
Properties:
StatusCode: The actual HTTP status code receivedExpectedStatusCodes: Set of status codes the client expectedMessage: Response body content (often contains server error details)
Example:
try
{
await client.Roles.Create("existing-role", permissions);
}
catch (WeaviateUnexpectedStatusCodeException ex)
{
Console.WriteLine($"Unexpected status: {ex.StatusCode}");
Console.WriteLine($"Expected: {string.Join(", ", ex.ExpectedStatusCodes)}");
Console.WriteLine($"Server message: {ex.Message}");
}Note: This is an internal exception type. Higher-level methods often catch this and throw more specific exceptions (like WeaviateConflictException or WeaviateNotFoundException).
Resource not found (HTTP 404 or gRPC NotFound).
public class WeaviateNotFoundException : WeaviateServerException
{
public ResourceType? ResourceType { get; }
}When thrown:
- Collection doesn't exist
- Object ID not found
- Role or user doesn't exist
- Backup not found
Example:
try
{
var collection = await client.Collections.Get("NonExistentCollection");
}
catch (WeaviateNotFoundException ex)
{
Console.WriteLine($"Not found: {ex.ResourceType}");
// Create the resource or handle the missing case
}Resource already exists (HTTP 409 Conflict).
public class WeaviateConflictException : WeaviateServerExceptionWhen thrown:
- Attempting to create a collection that already exists
- Creating a role with a duplicate name
- Creating an alias that conflicts with existing resources
Example:
try
{
await client.Roles.Create("admin", permissions);
}
catch (WeaviateConflictException ex)
{
Console.WriteLine($"Conflict: {ex.Message}");
// Resource already exists; decide whether to update or skip
}Feature not supported by the connected Weaviate server version.
public class WeaviateFeatureNotSupportedException : WeaviateServerExceptionWhen thrown:
- Using gRPC aggregate on servers without the aggregate RPC method
- Accessing features added in newer Weaviate versions
- Server built without optional modules
Example:
try
{
var results = await collection.Aggregate.OverAll();
}
catch (WeaviateFeatureNotSupportedException ex)
{
Console.WriteLine($"Feature not supported: {ex.Message}");
// Fall back to alternative approach or upgrade server
}Best practice: Check server version before using version-specific features:
if (client.WeaviateVersion >= new Version("1.25.0"))
{
// Use newer feature
}
else
{
// Use fallback or skip
}Backup or restore operation conflict - another backup/restore is already in progress.
public class WeaviateBackupConflictException : WeaviateServerExceptionWhen thrown:
- Starting a backup while another backup is running
- Starting a restore while another restore is running
- Starting either operation while any backup/restore is in progress
Example:
try
{
await client.Backup.Create("backup-1", BackupStorage.Filesystem);
}
catch (WeaviateBackupConflictException ex)
{
Console.WriteLine("Another backup/restore is in progress");
// Wait and retry, or cancel the existing operation
}WeaviateRestClientException - Client-side REST errors
public class WeaviateRestClientException : WeaviateClientExceptionIssues with REST request construction or HTTP communication.
WeaviateRestServerException - Server-side REST errors
public class WeaviateRestServerException : WeaviateServerExceptionErrors returned by REST endpoints.
WeaviateGrpcServerException - gRPC protocol errors
public class WeaviateGrpcServerException : WeaviateServerExceptionWraps Grpc.Core.RpcException with additional context.
Most operations follow this pattern:
try
{
var result = await client.SomeOperation();
// Process result
}
catch (WeaviateNotFoundException ex)
{
// Handle missing resource
Console.WriteLine("Resource not found");
}
catch (WeaviateConflictException ex)
{
// Handle duplicate resource
Console.WriteLine("Resource already exists");
}
catch (WeaviateServerException ex)
{
// Handle other server errors
Console.WriteLine($"Server error: {ex.Message}");
}
catch (WeaviateClientException ex)
{
// Handle client errors
Console.WriteLine($"Client error: {ex.Message}");
}When you need to handle specific HTTP status codes:
try
{
await client.SomeOperation();
}
catch (WeaviateUnexpectedStatusCodeException ex)
{
switch (ex.StatusCode)
{
case HttpStatusCode.BadRequest:
Console.WriteLine("Invalid request");
break;
case HttpStatusCode.Unauthorized:
Console.WriteLine("Authentication required");
break;
case HttpStatusCode.Forbidden:
Console.WriteLine("Permission denied");
break;
default:
Console.WriteLine($"Unexpected error: {ex.StatusCode}");
break;
}
}Example with exponential backoff:
async Task<T> RetryOperation<T>(Func<Task<T>> operation, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
try
{
return await operation();
}
catch (WeaviateServerException ex) when (i < maxRetries - 1)
{
var delay = TimeSpan.FromSeconds(Math.Pow(2, i));
Console.WriteLine($"Retry {i + 1}/{maxRetries} after {delay.TotalSeconds}s");
await Task.Delay(delay);
}
}
throw new Exception("Max retries exceeded");
}Check server capabilities before using features:
try
{
if (client.WeaviateVersion < new Version("1.28.0"))
{
Console.WriteLine("RBAC requires Weaviate >= 1.28.0");
return;
}
await client.Users.Database.Create("newuser");
}
catch (WeaviateFeatureNotSupportedException ex)
{
Console.WriteLine("Server doesn't support this feature");
}Some operations are designed to succeed regardless of resource existence:
Roles.Delete() - Returns success even if the role doesn't exist:
// No exception thrown even if role doesn't exist
await client.Roles.Delete("non-existent-role"); // ✅ SucceedsThis allows safe cleanup without existence checks:
// Cleanup pattern - no try/catch needed
await client.Roles.Delete(tempRoleName);
await client.Users.Database.Delete(tempUserId);Some endpoints return semantic results instead of errors:
Roles.HasPermission() - Returns false for non-existent roles:
// Returns false instead of throwing NotFoundException
var hasPermission = await client.Roles.HasPermission(
"non-existent-role",
new PermissionInfo("read_roles")
);
// hasPermission == false (not an exception)When to expect exceptions vs. semantic results:
| Operation | Non-existent resource behavior |
|---|---|
Roles.Get() |
Throws WeaviateNotFoundException |
Roles.HasPermission() |
Returns false |
Roles.Delete() |
Succeeds (idempotent) |
Collections.Get() |
Throws WeaviateNotFoundException |
Collections.Exists() |
Returns false |
// ✅ Good - specific to general
try
{
await operation();
}
catch (WeaviateNotFoundException) { /* handle not found */ }
catch (WeaviateConflictException) { /* handle conflict */ }
catch (WeaviateServerException) { /* handle other server errors */ }
// ❌ Bad - general exception hides specific cases
try
{
await operation();
}
catch (WeaviateException) { /* can't distinguish error types */ }// ✅ Good - proactive check
if (client.WeaviateVersion >= new Version("1.25.0"))
{
await UseNewFeature();
}
// ❌ Bad - reactive exception handling
try
{
await UseNewFeature();
}
catch (WeaviateFeatureNotSupportedException) { }// ✅ Good - cleanup always succeeds
try
{
await CreateTestResources();
await RunTests();
}
finally
{
// These succeed even if resources don't exist
await client.Roles.Delete(testRole);
await client.Users.Database.Delete(testUser);
}
// ❌ Bad - cleanup requires extra error handling
try
{
await client.Roles.Get(testRole);
await client.Roles.Delete(testRole);
}
catch (WeaviateNotFoundException) { }try
{
await client.Collections.Get(collectionName);
}
catch (WeaviateNotFoundException)
{
throw new ApplicationException(
$"Collection '{collectionName}' not found. " +
"Ensure the collection was created before use."
);
}// ❌ Bad - silently swallows errors
try
{
await CriticalOperation();
}
catch (WeaviateException) { }
// ✅ Good - log and/or rethrow
try
{
await CriticalOperation();
}
catch (WeaviateException ex)
{
_logger.LogError(ex, "Critical operation failed");
throw;
}// ✅ Good - uses semantic check
if (await client.Collections.Exists(name))
{
await client.Collections.Delete(name);
}
// ❌ Bad - uses exceptions for flow control
try
{
await client.Collections.Get(name);
await client.Collections.Delete(name);
}
catch (WeaviateNotFoundException) { }Related Documentation: