{"record":{"id":"2decb0010344fb4d","repo":"dagger/dagger","slug":"calling-snapshotter-remove-is-forbidden","errorCode":null,"errorMessage":"calling snapshotter.Remove is forbidden","messagePattern":"calling snapshotter\\.Remove is forbidden","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/snapshots/containerd/snapshotter.go","lineNumber":62,"sourceCode":"}\n\nfunc (s *nsSnapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {\n\tctx = namespaces.WithNamespace(ctx, s.ns)\n\treturn s.Snapshotter.Prepare(ctx, key, parent, opts...)\n}\n\nfunc (s *nsSnapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {\n\tctx = namespaces.WithNamespace(ctx, s.ns)\n\treturn s.Snapshotter.View(ctx, key, parent, opts...)\n}\n\nfunc (s *nsSnapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {\n\tctx = namespaces.WithNamespace(ctx, s.ns)\n\treturn s.Snapshotter.Commit(ctx, name, key, opts...)\n}\n\nfunc (s *nsSnapshotter) Remove(ctx context.Context, key string) error {\n\treturn errors.Errorf(\"calling snapshotter.Remove is forbidden\")\n}\n\nfunc (s *nsSnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, filters ...string) error {\n\tctx = namespaces.WithNamespace(ctx, s.ns)\n\treturn s.Snapshotter.Walk(ctx, fn, filters...)\n}\n\ntype fromContainerd struct {\n\tname string\n\tsnapshots.Snapshotter\n}\n\nfunc (s *fromContainerd) Name() string {\n\treturn s.name\n}\n\nfunc (s *fromContainerd) Mounts(ctx context.Context, key string) (bksnapshots.MountableRef, error) {\n\tmounts, err := s.Snapshotter.Mounts(ctx, key)","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/engine/snapshots/containerd/snapshotter.go#L44-L80","documentation":"The nsSnapshotter wrapper overrides Remove to always return 'calling snapshotter.Remove is forbidden'. Deleting snapshots directly from the containerd snapshotter would corrupt buildkit's own cache/reference accounting, so the operation is intentionally blocked and any call is a contract violation.","triggerScenarios":"Any code calling nsSnapshotter.Remove(ctx, key) — e.g. custom cleanup of snapshot keys, or migrated buildkit code assuming a standard snapshotter interface.","commonSituations":"Cleanup scripts or extensions trying to delete stale snapshot keys; porting code that uses a raw containerd snapshotter to this wrapper; manual GC implementations.","solutions":["Remove the call — snapshot removal must go through buildkit's cache manager, not the raw snapshotter.","Use the cache manager's Release/prune APIs so references are tracked correctly.","If cleanup is required out-of-band, understand snapshot keys may still be referenced and cause corruption."],"exampleFix":"// before\nif err := sn.Remove(ctx, key); err != nil { return err }\n// after\n// release via the cache manager instead\ncm.Release(ctx, ref)","handlingStrategy":"validation","validationCode":"// never call Remove on the wrapped snapshotter\n// audit code for `snapshotter.Remove(` / `sn.Remove(` before shipping","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Release snapshots through the cache manager only","Do not port raw containerd cleanup code onto this wrapper","Use prune APIs for cleanup"],"tags":["snapshotter","forbidden","remove","guard"],"backgroundTag":"snapshotter-remove-forbidden","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}