containerd/containerd · error · errdefs.ErrNotFound

snapshot does not exist: %w

Error message

snapshot does not exist: %w

What it means

UpdateSnapshot (bolt-backed snapshot storage) looks up the snapshot's bucket by name before applying an update. If no bucket exists for that name, the snapshot does not exist in the metadata store and errdefs.ErrNotFound is wrapped. The update transaction aborts without modification.

Source

Thrown at core/snapshots/storage/bolt.go:105

		getUsage(bkt, &su)
		return readSnapshot(bkt, &id, &si)
	})
	if err != nil {
		return "", snapshots.Info{}, snapshots.Usage{}, err
	}

	return strconv.FormatUint(id, 10), si, su, nil
}

// UpdateInfo updates an existing snapshot info's data
func UpdateInfo(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) {
	updated := snapshots.Info{
		Name: info.Name,
	}
	err := withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
		sbkt := bkt.Bucket([]byte(info.Name))
		if sbkt == nil {
			return fmt.Errorf("snapshot does not exist: %w", errdefs.ErrNotFound)
		}
		if err := readSnapshot(sbkt, nil, &updated); err != nil {
			return err
		}

		if len(fieldpaths) > 0 {
			for _, path := range fieldpaths {
				if strings.HasPrefix(path, "labels.") {
					if updated.Labels == nil {
						updated.Labels = map[string]string{}
					}

					key := strings.TrimPrefix(path, "labels.")
					updated.Labels[key] = info.Labels[key]
					continue
				}

				switch path {

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Verify the snapshot exists (e.g. via Statistics/Usage/GetInfo) before calling Update.
  2. Check the name/fieldpaths arguments for typos.
  3. Handle errdefs.IsNotFound(err) gracefully in the caller — the snapshot may have been concurrently deleted.
  4. Ensure the correct context (with the same storage transaction/DB) is used.

Example fix

// before
_, err := storage.Update(ctx, name, fieldpaths, info) // panics on missing snapshot
// after
if err := storage.GetInfo(ctx, name); err != nil && errdefs.IsNotFound(err) {
    return nil // snapshot gone; skip update
}
_, err := storage.Update(ctx, name, fieldpaths, info)
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := storage.GetInfo(ctx, name); err != nil {
    return err // snapshot already absent; skip update
}

Type guard

func snapshotGone(err error) bool { return errdefs.IsNotFound(err) }

Try / catch

_, err := storage.Update(ctx, name, fieldpaths, info)
if errdefs.IsNotFound(err) {
    return nil // concurrently removed; treat as no-op
}
return err

Prevention

When it happens

Trigger: Calling snapshots storage Update (UpdateSnapshot) with an info.Name that has no existing snapshot bucket — updating a snapshot that was already removed, never created, or whose name is wrong.

Common situations: Double-removal race where a snapshot is deleted between lookup and update; referencing a snapshot in a different bolt DB/context transaction; stale cache of snapshot names.

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/6561277e69c3bd52. Report an issue: GitHub.