{"record":{"id":"0e120225b2f12634","repo":"dagger/dagger","slug":"wait-for-dagql-cache-quiescence-w","errorCode":null,"errorMessage":"wait for dagql cache quiescence: %w","messagePattern":"wait for dagql cache quiescence: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"dagql/cache.go","lineNumber":3798,"sourceCode":"\t\t\tEmitOTelWait(stackCtx, lazySpan.SpanContext(), wcprof.WaitReasonLazy, otelWaitStartNS, time.Now().UnixNano())\n\t\t}\n\t\tif retry {\n\t\t\tcontinue\n\t\t}\n\t\treturn waitErr\n\t}\n}\n\nfunc (c *Cache) Close(ctx context.Context) error {\n\tc.closeOnce.Do(func() {\n\t\tslog.Info(\n\t\t\t\"starting dagql cache close\",\n\t\t\t\"hasSQLDB\", c.sqlDB != nil,\n\t\t\t\"hasPersistDB\", c.pdb != nil,\n\t\t)\n\t\tif err := c.waitForQuiescence(ctx); err != nil {\n\t\t\tslog.Error(\"dagql cache close failed waiting for quiescence; persistence will remain dirty\", \"err\", err)\n\t\t\tc.closeErr = errors.Join(c.closeErr, fmt.Errorf(\"wait for dagql cache quiescence: %w\", err))\n\t\t}\n\t\tif err := c.releaseCleanupError(); err != nil {\n\t\t\tslog.Error(\"dagql cache close found session cleanup errors; persistence will remain dirty\", \"err\", err)\n\t\t\tc.closeErr = errors.Join(c.closeErr, err)\n\t\t}\n\t\tif c.closeErr == nil {\n\t\t\tif err := c.persistCurrentState(ctx); err != nil {\n\t\t\t\tslog.Error(\"failed to persist dagql cache during close\", \"err\", err)\n\t\t\t\tc.closeErr = errors.Join(c.closeErr, err)\n\t\t\t}\n\t\t}\n\t\tif c.closeErr != nil {\n\t\t\tif closeErr := closeCacheDBs(c.sqlDB, c.pdb); closeErr != nil {\n\t\t\t\tslog.Error(\"failed to close dagql persistence databases after cache close error\", \"err\", closeErr)\n\t\t\t\tc.closeErr = errors.Join(c.closeErr, closeErr)\n\t\t\t}\n\t\t\tc.sqlDB = nil\n\t\t\tc.pdb = nil","sourceCodeStart":3780,"sourceCodeEnd":3816,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/dagql/cache.go#L3780-L3816","documentation":"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.","triggerScenarios":"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.","commonSituations":"Engine shutdown racing long-running queries; CI timeouts cancelling contexts before Close; leaked operations that never finish, making quiescence impossible.","solutions":["Read the logged underlying err for the real cause (deadline vs cancellation vs internal).","Pass a context with an adequate deadline to Close, and don't cancel it before shutdown completes.","Ensure all queries/lazy evaluations are drained or cancelled gracefully before Close.","If persistence integrity matters, treat this close as failed and re-run the affected work (persistence may be dirty)."],"exampleFix":"// before\ncache.Close(ctx) // ctx already cancelled\n\n// after\nshutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\nif err := cache.Close(shutdownCtx); err != nil {\n\tslog.Error(\"cache close incomplete; persistence may be dirty\", \"err\", err)\n}","handlingStrategy":"try-catch","validationCode":"if ctx.Err() != nil {\n\treturn errors.New(\"shutdown context already cancelled; give Close its own deadline\")\n}","typeGuard":null,"tryCatchPattern":"if err := cache.Close(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"wait for dagql cache quiescence\") {\n\t\tslog.Error(\"cache close timed out; persistence may be dirty\", \"err\", err)\n\t}\n}","preventionTips":["Give Close a dedicated context with a generous timeout, independent of request contexts.","Cancel or await all in-flight queries before shutdown.","Watch for leaked operations that prevent quiescence in long-lived engines."],"tags":["dagql","cache","shutdown","quiescence","persistence"],"backgroundTag":"cache-close-not-quiescent","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"}