dagger/dagger · warning

failed to release applier

Error message

failed to release applier

What it means

After diffApply finishes, the applier's Release() is deferred to free resources; if Release fails while the main body also failed, the release error is wrapped as 'failed to release applier' and appended via multierror so the original error is preserved. On its own it signals leaked or not-properly-closed applier resources (snapshot refs/mounts).

Source

Thrown at engine/snapshots/diffapply_linux.go:36

	"github.com/dagger/dagger/internal/buildkit/identity"
	"github.com/dagger/dagger/internal/buildkit/util/bklog"
	"github.com/hashicorp/go-multierror"
	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)

// diffApply applies the provided diffs to the dest MountableRef and returns the correctly calculated disk usage
// that accounts for any hardlinks made from existing snapshots. ctx is expected to have a temporary lease
// associated with it.
func (sn *mergeSnapshotter) diffApply(ctx context.Context, dest MountableRef, diffs ...Diff) (_ snapshots.Usage, rerr error) {
	a, err := applierFor(dest, sn.tryCrossSnapshotLink, sn.userxattr)
	if err != nil {
		return snapshots.Usage{}, errors.Wrapf(err, "failed to create applier")
	}
	defer func() {
		releaseErr := a.Release()
		if releaseErr != nil {
			rerr = multierror.Append(rerr, errors.Wrapf(releaseErr, "failed to release applier")).ErrorOrNil()
		}
	}()

	for _, diff := range diffs {
		var lowerMntable MountableRef
		if diff.Lower != "" {
			if info, err := sn.Stat(ctx, diff.Lower); err != nil {
				return snapshots.Usage{}, errors.Wrapf(err, "failed to stat lower snapshot %s", diff.Lower)
			} else if info.Kind == snapshots.KindCommitted {
				lowerMntable, err = sn.View(ctx, identity.NewID(), diff.Lower)
				if err != nil {
					return snapshots.Usage{}, errors.Wrapf(err, "failed to mount lower snapshot view %s", diff.Lower)
				}
			} else {
				lowerMntable, err = sn.Mounts(ctx, diff.Lower)
				if err != nil {
					return snapshots.Usage{}, errors.Wrapf(err, "failed to mount lower snapshot %s", diff.Lower)
				}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Look at the full multierror output — the release error often accompanies a primary error that is the real cause.
  2. Check for busy mounts (mount | grep <path>) and unmount leftovers.
  3. Verify no leaked references keep the snapshot alive; run prune to clean stale state.
  4. Restart the engine if mounts are stuck after crash.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await mergeOp();
} catch (e) {
  const parts = String(e).split('\n');
  const primary = parts[0];
  if (parts.some(p => p.includes('failed to release applier'))) {
    // release failure is secondary; focus on primary, then unmount leftovers
    cleanupMounts();
  }
  throw new Error(primary);
}

Prevention

When it happens

Trigger: a.Release() returns an error at function exit — e.g. releasing snapshot references or unmounting the destination fails; it can also mask/join with the primary error via multierror.

Common situations: Busy mounts preventing unmount (EBUSY); leaked references held elsewhere; destination snapshot already removed; cascading after an earlier failure in the same call.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/6304244fd830af63. Report an issue: GitHub.