kopia/kopia · error
getContent
Error message
getContent
What it means
EncryptionManager.GetEncryptedBlob fetches the raw index blob through an in-memory cache (indexBlobCache.GetOrLoad) whose loader calls st.GetBlob to read the full blob. Any failure from the cache or underlying storage GetBlob is wrapped as "getContent". The name reflects the legacy internal loader function that retrieves the (still encrypted) blob content.
Solutions
- Check the wrapped cause for blob-not-found: if the blob was deleted by cleanup, the referencing index metadata is stale — refresh/compact it.
- Verify the blobID exists in storage (list blobs with the same prefix) and that credentials/network to the backend work.
- Retry transient storage errors; the cache loader will re-attempt st.GetBlob.
- If caused by cleanup racing compaction, tune cleanup delay or re-register the index blobs.
Example fix
// before
payload, err := mgr.GetEncryptedBlob(ctx, blobID) // blob may be deleted
// after
payload, err := mgr.GetEncryptedBlob(ctx, blobID)
if err != nil && blob.ErrBlobNotFound.Is(err) {
return refreshIndexAndRetry(ctx, blobID)
} Defensive patterns
Strategy: try-catch
Validate before calling
md, err := st.GetMetadata(ctx, blobID) exists := err == nil
Try / catch
payload, err := mgr.GetEncryptedBlob(ctx, blobID)
if err != nil {
if blob.IsBlobNotFound(err) {
// refresh index metadata or re-compact; blob was cleaned up
}
return err
} Prevention
- Check blob existence (GetMetadata) before expecting to read index blobs.
- Tune cleanup delay so referenced index blobs are not garbage-collected during reads.
- Handle transient storage/network errors with retries.
When it happens
Trigger: Calling GetEncryptedBlob when the blob does not exist in storage, the storage backend errors, or the cache loader's st.GetBlob call fails for the given blobID.
Common situations: Blob already garbage-collected by cleanup while an index still references it; network/auth failures to object storage; wrong object ID passed by compaction-log or cleanup entry processing.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- error writing deletion watermark
- error writing index blob
- failed to get blob with ID
- unable to delete pack blob
- BLOB not found
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/b0324480a78aca9f.
Report an issue: GitHub.
Appendix: source
Thrown at repo/content/indexblob/index_blob_encryption.go:97
// EncryptionManager manages encryption and caching of index blobs.
type EncryptionManager struct {
st blob.Storage
crypter blobcrypto.Crypter
indexBlobCache *cache.PersistentCache
log *contentlog.Logger
}
// GetEncryptedBlob fetches and decrypts the contents of a given encrypted blob
// using cache first and falling back to the underlying storage.
func (m *EncryptionManager) GetEncryptedBlob(ctx context.Context, blobID blob.ID, output *gather.WriteBuffer) error {
var payload gather.WriteBuffer
defer payload.Close()
if err := m.indexBlobCache.GetOrLoad(ctx, string(blobID), func(output *gather.WriteBuffer) error {
return m.st.GetBlob(ctx, blobID, 0, -1, output)
}, &payload); err != nil {
return errors.Wrap(err, "getContent")
}
return errors.Wrap(blobcrypto.Decrypt(m.crypter, payload.Bytes(), blobID, output), "decrypt blob")
}
// EncryptAndWriteBlob encrypts and writes the provided data into a blob,
// with name {prefix}{hash}[-{suffix}].
func (m *EncryptionManager) EncryptAndWriteBlob(ctx context.Context, data gather.Bytes, prefix, suffix blob.ID) (blob.Metadata, error) {
var data2 gather.WriteBuffer
defer data2.Close()
blobID, err := blobcrypto.Encrypt(m.crypter, data, prefix, suffix, &data2)
if err != nil {
return blob.Metadata{}, errors.Wrap(err, "error encrypting")
}
t0 := timetrack.StartTimer()
View on GitHub (pinned to 82495e54b5)