{"record":{"id":"29fc18699503d9af","repo":"dagger/dagger","slug":"operation-lease-scope-already-released","errorCode":null,"errorMessage":"operation lease scope already released","messagePattern":"operation lease scope already released","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/snapshots/lease.go","lineNumber":75,"sourceCode":"\nfunc WithoutLazyLease(ctx context.Context) context.Context {\n\tif lazyLeaseFromContext(ctx) == nil {\n\t\treturn ctx\n\t}\n\treturn context.WithValue(ctx, lazyLeaseScopeKey{}, withoutLazyLeaseScope{})\n}\n\nfunc lazyLeaseFromContext(ctx context.Context) *lazyLeaseScope {\n\tscope, _ := ctx.Value(lazyLeaseScopeKey{}).(*lazyLeaseScope)\n\treturn scope\n}\n\nfunc (s *lazyLeaseScope) ensure(ctx context.Context) (context.Context, error) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif s.released {\n\t\treturn ctx, fmt.Errorf(\"operation lease scope already released\")\n\t}\n\tif s.lease != nil {\n\t\treturn leases.WithLease(ctx, s.lease.l.ID), nil\n\t}\n\tlease, leaseCtx, err := NewLease(ctx, s.lm, s.opts...)\n\tif err != nil {\n\t\treturn ctx, err\n\t}\n\ts.lease = lease\n\treturn leaseCtx, nil\n}\n\nfunc (s *lazyLeaseScope) release(ctx context.Context) error {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif s.released {\n\t\treturn nil","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/engine/snapshots/lease.go#L57-L93","documentation":"lazyLeaseScope.ensure (engine/snapshots/lease.go:75) returns this error when code attempts to use a lease scope after its Unmount/Release was called. Once released, the scope can no longer attach a lease to the context, so any subsequent ensure fails immediately.","triggerScenarios":"Calling any operation that goes through lazyLeaseScope (e.g. a mount or snapshot access via EnsureLease) after the scope's Release was already invoked — typically use-after-release of a LocalMounter/lease-managed resource or concurrent access racing Release.","commonSituations":"Calling Unmount then re-using the same LocalMounter/lease scope; goroutine race where one goroutine releases while another still resolves the context; long-lived references to a mount kept beyond its cleanup.","solutions":["Re-create the lease scope / LocalMounter instead of reusing a released one.","Ensure Release/Unmount is called only after all work with the scope is finished (use defer with correct ordering).","Serialize access: do not call operations on the scope concurrently with Release; guard with the existing mutex/sync discipline.","If this appears in tests, obtain a fresh scope per test case rather than sharing a fixture-released one."],"exampleFix":"// before\nmounter, _ := NewLocalMounter(ctx, ...)\ntarget, _ := mounter.Mount(ctx)\nmounter.Unmount(ctx)\ntarget2, err := mounter.Mount(ctx) // operation lease scope already released\n// after\nmounter, _ := NewLocalMounter(ctx, ...)\ntarget, err := mounter.Mount(ctx)\n// ... use target ...\ndefer mounter.Unmount(ctx) // release exactly once, after last use","handlingStrategy":"type-guard","validationCode":"// track release state yourself before reuse\ntype guardedScope struct {\n\tmu       sync.Mutex\n\treleased bool\n}\nfunc (g *guardedScope) ensureUsable() error {\n\tg.mu.Lock(); defer g.mu.Unlock()\n\tif g.released {\n\t\treturn errors.New(\"scope already released; create a new one\")\n\t}\n\treturn nil\n}","typeGuard":"func scopeUsable(mu *sync.Mutex, released *bool) bool {\n\tmu.Lock(); defer mu.Unlock()\n\treturn !*released\n}","tryCatchPattern":"target, err := mounter.Mount(ctx)\nif err != nil && strings.Contains(err.Error(), \"operation lease scope already released\") {\n\t// recreate scope instead of failing\n\tmounter, err = NewLocalMounter(ctx, ref)\n\tif err == nil {\n\t\ttarget, err = mounter.Mount(ctx)\n\t}\n}","preventionTips":["Always release via defer immediately after Mount succeeds","Never reuse a mounter/scope after Unmount; construct a new one","Serialize Release with all other scope operations"],"tags":["lease","lifecycle","snapshots","race"],"backgroundTag":"lease-scope-released","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"}