{"record":{"id":"df77362af400d7ae","repo":"jackc/pgx","slug":"watch-already-in-progress","errorCode":null,"errorMessage":"watch already in progress","messagePattern":"watch already in progress","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgconn/ctxwatch/context_watcher.go","lineNumber":37,"sourceCode":"\n// NewContextWatcher returns a ContextWatcher. onCancel will be called when a watched context is canceled.\n// OnUnwatchAfterCancel will be called when Unwatch is called and the watched context had already been canceled and\n// onCancel called.\nfunc NewContextWatcher(handler Handler) *ContextWatcher {\n\tcw := &ContextWatcher{\n\t\thandler: handler,\n\t}\n\n\treturn cw\n}\n\n// Watch starts watching ctx. If ctx is canceled then the onCancel function passed to NewContextWatcher will be called.\nfunc (cw *ContextWatcher) Watch(ctx context.Context) {\n\tcw.lock.Lock()\n\tdefer cw.lock.Unlock()\n\n\tif cw.stop != nil {\n\t\tpanic(\"watch already in progress\")\n\t}\n\n\tif ctx.Done() != nil {\n\t\tcw.done = make(chan struct{})\n\t\tcw.stop = context.AfterFunc(ctx, func() {\n\t\t\tcw.handler.HandleCancel(ctx)\n\t\t\tclose(cw.done)\n\t\t})\n\t}\n}\n\n// Unwatch stops watching the previously watched context. If the onCancel function passed to NewContextWatcher was\n// called then onUnwatchAfterCancel will also be called.\nfunc (cw *ContextWatcher) Unwatch() {\n\tcw.lock.Lock()\n\tdefer cw.lock.Unlock()\n\n\tif cw.stop != nil {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/pgconn/ctxwatch/context_watcher.go#L19-L55","documentation":"ContextWatcher.Watch panics when a watch is already active (stop channel non-nil), i.e. Watch was called twice without an intervening Unwatch — the watcher tracks a single context at a time.","triggerScenarios":"Thrown at pgconn/ctxwatch/context_watcher.go:37 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Call Unwatch before starting a new Watch","Watch a single all-encompassing context instead of swapping contexts mid-operation","Pair Watch/Unwatch calls symmetrically at call sites (e.g. defer Unwatch immediately after Watch)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}