kopia/kopia · error
unable to open persistent cache
Error message
unable to open persistent cache
What it means
The persistent content cache could not be opened: cache.NewPersistentCache failed after key derivation and protection setup succeeded. Causes include an unwritable or missing cache storage directory, a corrupt existing cache (bad index/manifest files), or storage backend errors. Without the cache the API-server repository cannot open.
Solutions
- Check the wrapped cause; if cache corruption, delete the cache directory (safe — it is rebuilt)
- Ensure the cache directory path is writable by the process user and the disk is not full
- Verify KOPIA_CACHE_DIRECTORY / caching options point to a valid local path
- Check that ContentCacheSizeLimitBytes >= ContentCacheSizeBytes and other sweep settings are sane
Example fix
// before cachingOptions.CacheDirectory = "/mnt/ro/cache" // after cachingOptions.CacheDirectory = filepath.Join(os.TempDir(), "kopia-cache")
Defensive patterns
Strategy: try-catch
Validate before calling
if st, err := os.Stat(cacheDir); err != nil || !st.IsDir() {
os.MkdirAll(cacheDir, 0o700)
}
// check writability
test := filepath.Join(cacheDir, ".write-test")
if err := os.WriteFile(test, nil, 0o600); err != nil {
return fmt.Errorf("cache dir %v not writable: %w", cacheDir, err)
}
os.Remove(test) Try / catch
pc, err := cache.NewPersistentCache(...)
if err != nil {
log.Printf("cache open failed (%v); retrying with clean cache dir", err)
os.RemoveAll(cacheDir)
pc, err = cache.NewPersistentCache(...) // retry with fresh cache
} Prevention
- Point KOPIA_CACHE_DIRECTORY at local writable disk, never network/RO mounts
- Monitor disk space on the cache volume
- Delete (never edit) cache contents when troubleshooting — it is safe to remove
When it happens
Trigger: getContentCacheOrNil calls cache.NewPersistentCache with a LocalStorage provider pointing at cachingOptions.CacheDirectory; fails when the directory cannot be created/opened, permissions deny access, or cached metadata is corrupt. Also fires when sweep settings (ContentCacheSizeLimitBytes) are invalid.
Common situations: Read-only $HOME or KOPIA_CACHE_DIRECTORY on a full disk; cache directory deleted mid-run leaving partial files; Docker container with a read-only volume mounted at the cache path; negative/zero size-limit options.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- error adding content to cache
- error creating list cache directory
- error determining whether index blob
- error getting temporary dir
- error initializing cache storage
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/45aac9e035cf7a2e.
Report an issue: GitHub.
Appendix: source
Thrown at repo/open.go:175
}
cacheEncryptionKey, err := crypto.DeriveKeyFromPassword(password, saltWithPurpose, cacheEncryptionKeySize, keyAlgo)
if err != nil {
return nil, errors.Wrap(err, "unable to derive cache encryption key from password")
}
prot, err := cacheprot.AuthenticatedEncryptionProtection(cacheEncryptionKey)
if err != nil {
return nil, errors.Wrap(err, "unable to initialize protection")
}
pc, err := cache.NewPersistentCache(ctx, "cache-storage", cs, prot, cache.SweepSettings{
MaxSizeBytes: opt.ContentCacheSizeBytes,
LimitBytes: opt.ContentCacheSizeLimitBytes,
MinSweepAge: opt.MinContentSweepAge.DurationOrDefault(content.DefaultDataCacheSweepAge),
}, mr, timeNow)
if err != nil {
return nil, errors.Wrap(err, "unable to open persistent cache")
}
return pc, nil
}
// openAPIServer connects remote repository over Kopia API.
func openAPIServer(ctx context.Context, si *APIServerInfo, cliOpts ClientOptions, cachingOptions *content.CachingOptions, password string, options *Options) (Repository, error) {
cachingOptions = cachingOptions.CloneOrDefault()
mr := metrics.NewRegistry()
contentCache, err := getContentCacheOrNil(ctx, si, cachingOptions, password, mr, options.TimeNowFunc)
if err != nil {
return nil, errors.Wrap(err, "error opening content cache")
}
closer := newRefCountedCloser(
func(ctx context.Context) error {View on GitHub (pinned to 82495e54b5)