dagger/dagger · warning

wait for dagql cache quiescence: %w

Error message

wait for dagql cache quiescence: %w

What it means

During Cache.Close, waitForQuiescence blocks until all in-flight cache operations and lazy evaluations have settled before persisting state. If it fails (context deadline, cancellation, or an internal error), the cache's persistence may be left dirty; the error is recorded into closeErr via errors.Join with this message prefix, and logged, but Close continues.

Source

Thrown at dagql/cache.go:3798

			EmitOTelWait(stackCtx, lazySpan.SpanContext(), wcprof.WaitReasonLazy, otelWaitStartNS, time.Now().UnixNano())
		}
		if retry {
			continue
		}
		return waitErr
	}
}

func (c *Cache) Close(ctx context.Context) error {
	c.closeOnce.Do(func() {
		slog.Info(
			"starting dagql cache close",
			"hasSQLDB", c.sqlDB != nil,
			"hasPersistDB", c.pdb != nil,
		)
		if err := c.waitForQuiescence(ctx); err != nil {
			slog.Error("dagql cache close failed waiting for quiescence; persistence will remain dirty", "err", err)
			c.closeErr = errors.Join(c.closeErr, fmt.Errorf("wait for dagql cache quiescence: %w", err))
		}
		if err := c.releaseCleanupError(); err != nil {
			slog.Error("dagql cache close found session cleanup errors; persistence will remain dirty", "err", err)
			c.closeErr = errors.Join(c.closeErr, err)
		}
		if c.closeErr == nil {
			if err := c.persistCurrentState(ctx); err != nil {
				slog.Error("failed to persist dagql cache during close", "err", err)
				c.closeErr = errors.Join(c.closeErr, err)
			}
		}
		if c.closeErr != nil {
			if closeErr := closeCacheDBs(c.sqlDB, c.pdb); closeErr != nil {
				slog.Error("failed to close dagql persistence databases after cache close error", "err", closeErr)
				c.closeErr = errors.Join(c.closeErr, closeErr)
			}
			c.sqlDB = nil
			c.pdb = nil

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Read the logged underlying err for the real cause (deadline vs cancellation vs internal).
  2. Pass a context with an adequate deadline to Close, and don't cancel it before shutdown completes.
  3. Ensure all queries/lazy evaluations are drained or cancelled gracefully before Close.
  4. If persistence integrity matters, treat this close as failed and re-run the affected work (persistence may be dirty).

Example fix

// before
cache.Close(ctx) // ctx already cancelled

// after
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := cache.Close(shutdownCtx); err != nil {
	slog.Error("cache close incomplete; persistence may be dirty", "err", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if ctx.Err() != nil {
	return errors.New("shutdown context already cancelled; give Close its own deadline")
}

Try / catch

if err := cache.Close(ctx); err != nil {
	if strings.Contains(err.Error(), "wait for dagql cache quiescence") {
		slog.Error("cache close timed out; persistence may be dirty", "err", err)
	}
}

Prevention

When it happens

Trigger: Close called with an already-cancelled or deadline-exceeded context while evaluations are pending; a stuck in-flight evaluation preventing quiescence; shutdown timeouts in the engine.

Common situations: Engine shutdown racing long-running queries; CI timeouts cancelling contexts before Close; leaked operations that never finish, making quiescence impossible.

Related errors


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