Trove defines sentinel errors for all failure cases. Use errors.Is() to match specific error conditions regardless of wrapping.
Resource Errors01
Errors related to missing or duplicate resources:
| Error | Description |
ErrNotFound | A requested resource cannot be found |
ErrBucketNotFound | A bucket cannot be found |
ErrBucketExists | Creating a bucket that already exists |
ErrObjectNotFound | An object cannot be found |
Validation Errors02
Errors related to invalid input:
| Error | Description |
ErrKeyEmpty | Object key is empty (required field) |
ErrBucketEmpty | Bucket name is empty (required field) |
ErrInvalidDSN | DSN string cannot be parsed |
Driver Errors03
Errors related to driver lifecycle:
| Error | Description |
ErrDriverClosed | Operation attempted on a closed driver |
ErrNilDriver | Open called with a nil driver |
ErrBackendNotFound | Named backend does not exist in the router |
Integrity Errors04
Errors related to data integrity and security:
| Error | Description |
ErrChecksumMismatch | Checksum verification failed -- data may be corrupted |
ErrContentBlocked | Content rejected by scanning middleware (threat detected) |
Quota Errors05
| Error | Description |
ErrQuotaExceeded | Storage quota exceeded for the tenant or bucket |
Stream Errors06
Errors related to streaming and upload sessions:
| Error | Description |
ErrStreamClosed | Writing to a closed stream |
ErrStreamNotActive | Operation requires an active stream |
ErrUploadExpired | Resumable upload session has expired |
ErrPoolClosed | Stream pool has been shut down |
ErrMaxStreamsReached | Pool concurrency limit reached |
Matching Errors07
Always use errors.Is() to check for sentinel errors, since errors may be wrapped with additional context:
import (
"errors"
"github.com/xraph/trove"
)
reader, err := t.Get(ctx, "data", "report.csv")
if err != nil {
switch {
case errors.Is(err, trove.ErrObjectNotFound):
// Object does not exist -- return 404
http.Error(w, "Not found", http.StatusNotFound)
case errors.Is(err, trove.ErrBucketNotFound):
// Bucket does not exist -- return 404
http.Error(w, "Bucket not found", http.StatusNotFound)
case errors.Is(err, trove.ErrChecksumMismatch):
// Data corruption detected
log.Error("integrity failure", "err", err)
http.Error(w, "Data integrity error", http.StatusInternalServerError)
case errors.Is(err, trove.ErrDriverClosed):
// Driver shut down -- service unavailable
http.Error(w, "Service unavailable", http.StatusServiceUnavailable)
default:
http.Error(w, "Internal error", http.StatusInternalServerError)
}
return
}HTTP Status Code Mapping08
When Trove is used as an HTTP API, sentinel errors map to standard HTTP status codes:
| Error | HTTP Status | Code |
ErrNotFound | Not Found | 404 |
ErrBucketNotFound | Not Found | 404 |
ErrObjectNotFound | Not Found | 404 |
ErrBucketExists | Conflict | 409 |
ErrKeyEmpty | Bad Request | 400 |
ErrBucketEmpty | Bad Request | 400 |
ErrInvalidDSN | Bad Request | 400 |
ErrDriverClosed | Service Unavailable | 503 |
ErrNilDriver | Internal Server Error | 500 |
ErrBackendNotFound | Not Found | 404 |
ErrChecksumMismatch | Conflict | 409 |
ErrQuotaExceeded | Insufficient Storage | 507 |
ErrContentBlocked | Unprocessable Entity | 422 |
ErrStreamClosed | Gone | 410 |
ErrUploadExpired | Gone | 410 |
ErrPoolClosed | Service Unavailable | 503 |
ErrMaxStreamsReached | Too Many Requests | 429 |
Creating Application Errors09
Wrap Trove sentinel errors to add context without losing the ability to match:
import "fmt"
func getDocument(ctx context.Context, t *trove.Trove, docID string) error {
_, err := t.Get(ctx, "documents", docID)
if err != nil {
return fmt.Errorf("get document %s: %w", docID, err)
}
return nil
}
// Callers can still match the original error:
err := getDocument(ctx, t, "missing.pdf")
if errors.Is(err, trove.ErrObjectNotFound) {
// Matched despite wrapping
}