kopia/kopia · warning
operation supported only on direct repository
Error message
operation supported only on direct repository
What it means
attemptReadPackFileLocalIndex reads a section of a pack blob that supposedly contains the pack-local index, using sm.st.GetBlob with the pack file ID, offset and length. If GetBlob fails, the error is wrapped as "error getting blob %v" naming the pack file. This is the optimized-read path that tries to use each pack's embedded local index before falling back to the shared index.
Solutions
- Retry the operation — callers (readPackFileLocalIndex) fall back to the non-optimized index path, so transient errors are usually harmless.
- Check that the pack blob exists in the storage backend and that connectivity/credentials are valid.
- Run kopia maintenance (compact + garbage collection) to reconcile index state with actual blobs.
Example fix
// before
if err := readPackFileLocalIndex(ctx, packFile); err != nil {
return err // optimized-read failure aborts
}
// after
if err := readPackFileLocalIndex(ctx, packFile); err != nil {
log.Debugf("optimized local-index read failed for %v: %v; falling back", packFile, err)
return loadFromSharedIndex(ctx, packFile) // graceful fallback
} Defensive patterns
Strategy: fallback
Try / catch
if err := readPackFileLocalIndex(ctx, packFile); err != nil {
// optimized path is best-effort: log and fall back to shared index
log.Debugf("local index read failed: %v", err)
return sm.loadFromSharedIndex(ctx, packFile)
} Prevention
- Treat the optimized local-index path as best-effort; always have the shared-index fallback wired in.
- Avoid deleting pack blobs outside of kopia-managed garbage collection.
- Use strongly consistent storage when possible to reduce partial-read surprises.
When it happens
Trigger: readPackFileLocalIndex attempts the optimized path for a pack file whose blob cannot be fetched: blob missing from storage, network/backend error, or insufficient permissions during GetBlob(packFile, offset, length).
Common situations: Pack file garbage-collected or deleted by maintenance in another client; transient S3/network failure; eventually-consistent backend not yet showing a newly uploaded pack; corrupted provider credentials.
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
- caching not enabled
- error listing all blobs
- error loading index blob
- error reading schedule blob
- Reading blob in GetBlob
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/562abca64fe5bd15.
Report an issue: GitHub.
Appendix: source
Thrown at cli/app.go:428
}
return c.runAppWithContext(kpc.SelectedCommand, func(ctx context.Context) error {
return act(ctx, apiClient)
})
}
}
func assertDirectRepository(act func(ctx context.Context, rep repo.DirectRepository) error) func(ctx context.Context, rep repo.Repository) error {
return func(ctx context.Context, rep repo.Repository) error {
if rep == nil {
return act(ctx, nil)
}
// right now this assertion never fails,
// but will fail in the future when we have remote repository implementation
lr, ok := rep.(repo.DirectRepository)
if !ok {
return errors.New("operation supported only on direct repository")
}
return act(ctx, lr)
}
}
func (c *App) directRepositoryWriteAction(act func(ctx context.Context, rep repo.DirectRepositoryWriter) error) func(ctx *kingpin.ParseContext) error {
return c.repositoryAction(assertDirectRepository(func(ctx context.Context, rep repo.DirectRepository) error {
rep.LogManager().Enable()
return repo.DirectWriteSession(ctx, rep, repo.WriteSessionOptions{
Purpose: "cli:" + c.currentActionName(),
OnUpload: c.progress.UploadedBytes,
}, act)
}))
}
func (c *App) directRepositoryReadAction(act func(ctx context.Context, rep repo.DirectRepository) error) func(ctx *kingpin.ParseContext) error {View on GitHub (pinned to 82495e54b5)