Trove

Errors

Sentinel errors for storage operations: not found, quota exceeded, driver closed, and more.

Trove defines sentinel errors for all failure cases. Use errors.Is() to match specific error conditions regardless of wrapping.

Resource Errors

Errors related to missing or duplicate resources:

ErrorDescription
ErrNotFoundA requested resource cannot be found
ErrBucketNotFoundA bucket cannot be found
ErrBucketExistsCreating a bucket that already exists
ErrObjectNotFoundAn object cannot be found

Validation Errors

Errors related to invalid input:

ErrorDescription
ErrKeyEmptyObject key is empty (required field)
ErrBucketEmptyBucket name is empty (required field)
ErrInvalidDSNDSN string cannot be parsed

Driver Errors

Errors related to driver lifecycle:

ErrorDescription
ErrDriverClosedOperation attempted on a closed driver
ErrNilDriverOpen called with a nil driver
ErrBackendNotFoundNamed backend does not exist in the router

Integrity Errors

Errors related to data integrity and security:

ErrorDescription
ErrChecksumMismatchChecksum verification failed -- data may be corrupted
ErrContentBlockedContent rejected by scanning middleware (threat detected)

Quota Errors

ErrorDescription
ErrQuotaExceededStorage quota exceeded for the tenant or bucket

Stream Errors

Errors related to streaming and upload sessions:

ErrorDescription
ErrStreamClosedWriting to a closed stream
ErrStreamNotActiveOperation requires an active stream
ErrUploadExpiredResumable upload session has expired
ErrPoolClosedStream pool has been shut down
ErrMaxStreamsReachedPool concurrency limit reached

Matching Errors

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 Mapping

When Trove is used as an HTTP API, sentinel errors map to standard HTTP status codes:

ErrorHTTP StatusCode
ErrNotFoundNot Found404
ErrBucketNotFoundNot Found404
ErrObjectNotFoundNot Found404
ErrBucketExistsConflict409
ErrKeyEmptyBad Request400
ErrBucketEmptyBad Request400
ErrInvalidDSNBad Request400
ErrDriverClosedService Unavailable503
ErrNilDriverInternal Server Error500
ErrBackendNotFoundNot Found404
ErrChecksumMismatchConflict409
ErrQuotaExceededInsufficient Storage507
ErrContentBlockedUnprocessable Entity422
ErrStreamClosedGone410
ErrUploadExpiredGone410
ErrPoolClosedService Unavailable503
ErrMaxStreamsReachedToo Many Requests429

Creating Application Errors

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
}

On this page