{"record":{"id":"be5d6cea202400d4","repo":"vitessio/vitess","slug":"vreplication-engine-is-closed","errorCode":null,"errorMessage":"vreplication engine is closed","messagePattern":"vreplication engine is closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/engine.go","lineNumber":789,"sourceCode":"\t\t}\n\t\tvre.controllers[id] = ct\n\t}\n\tlog.Info(fmt.Sprintf(\"Completed transition for journal:workload %v\", je))\n}\n\n// WaitForPos waits for the replication to reach the specified position.\nfunc (vre *Engine) WaitForPos(ctx context.Context, id int32, pos string) error {\n\tstart := time.Now()\n\tmPos, err := binlogplayer.DecodePosition(pos)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := func() error {\n\t\tvre.mu.Lock()\n\t\tdefer vre.mu.Unlock()\n\t\tif !vre.isOpen {\n\t\t\treturn errors.New(\"vreplication engine is closed\")\n\t\t}\n\n\t\t// Ensure that the engine won't be closed while this is running.\n\t\tvre.wg.Add(1)\n\t\treturn nil\n\t}(); err != nil {\n\t\treturn err\n\t}\n\tdefer vre.wg.Done()\n\n\tif vre.shortcircuit {\n\t\treturn nil\n\t}\n\n\tdbClient := vre.dbClientFactoryFiltered()\n\tif err := dbClient.Connect(); err != nil {\n\t\treturn err\n\t}","sourceCodeStart":771,"sourceCodeEnd":807,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/engine.go#L771-L807","documentation":"Returned by the vreplication Engine when an operation (wrapped in the wg-tracked run function) is attempted after vre.Open() has not run or after Close() has been called. The engine holds mu and isOpen; any work requiring the engine (e.g. state transitions during shutdown) is rejected while it is closed.","triggerScenarios":"Calling engine methods that use the protected run wrapper while the vreplication engine is closed — commonly during or after Close(), or on a tablet where the vreplication engine failed to open at startup.","commonSituations":"VDiff or vreplication state queries racing with tablet shutdown; engine never opened because startup initialization failed; calling VReplicationExec on a tablet with vreplication disabled.","solutions":["Retry after the tablet finishes its shutdown/restart cycle","Confirm the tablet started with vreplication enabled and check startup logs for engine-open failures","Serialize admin operations (vdiff, workflow state changes) with tablet restarts so they don't race Close()","Reopen the engine by restarting vttablet if it was never opened"],"exampleFix":"// before\n// vdiff called while tablet is shutting down -> 'engine is closed'\n// after\n// wait for tablet readiness, then retry:\nvtctldclient Workflow --keyspace ks vdiff sales start  // after tablet is up","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := engineOp(); errors.Is(err, errClosed) || strings.Contains(err.Error(), \"engine is closed\") {\n    // wait for tablet restart, then retry with backoff\n    time.Sleep(2 * time.Second); retry()\n}","preventionTips":["Don't run vdiff/admin commands during tablet shutdown windows","Check tablet startup logs for vreplication engine open failures","Gate automation on tablet health/readiness checks"],"tags":["vreplication","lifecycle","shutdown"],"backgroundTag":"engine-closed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}