{"record":{"id":"57c1a68ec9bc0c67","repo":"vitessio/vitess","slug":"error-reading-vreplication-settings-v","errorCode":null,"errorMessage":"error reading VReplication settings: %v","messagePattern":"error reading VReplication settings: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/vreplicator.go","lineNumber":518,"sourceCode":"\t\t// Reconcile the exported state metric with the row we just read\n\t\t// from _vt.vreplication, which is the source of truth. setState()\n\t\t// advances stats.State before its DB UPDATE is sent, while vr.state\n\t\t// is only updated after a successful write; when that UPDATE fails\n\t\t// (e.g. the target is read-only during a reparent) the metric is\n\t\t// left out of sync with the persisted row. Re-syncing it here on\n\t\t// every successful read recovers the metric once the stream\n\t\t// resumes. vr.state is deliberately left alone: it already matches\n\t\t// the persisted row, and overwriting it would break the state\n\t\t// transitions Replicate() relies on. See #20012.\n\t\tvr.stats.State.Store(settings.State.String())\n\t}\n\treturn settings, numTablesToCopy, err\n}\n\nfunc (vr *vreplicator) readSettings(ctx context.Context, dbClient *vdbClient) (settings binlogplayer.VRSettings, numTablesToCopy int64, err error) {\n\tsettings, err = binlogplayer.ReadVRSettings(dbClient, vr.id)\n\tif err != nil {\n\t\treturn settings, numTablesToCopy, fmt.Errorf(\"error reading VReplication settings: %v\", err)\n\t}\n\n\tquery := fmt.Sprintf(\"select count(distinct table_name) from _vt.copy_state where vrepl_id=%d\", vr.id)\n\tqr, err := vr.dbClient.ExecuteFetch(query, maxRows)\n\tif err != nil {\n\t\treturn settings, numTablesToCopy, err\n\t}\n\tif len(qr.Rows) == 0 || len(qr.Rows[0]) == 0 {\n\t\treturn settings, numTablesToCopy, fmt.Errorf(\"unexpected result from %s: %v\", query, qr)\n\t}\n\tnumTablesToCopy, err = qr.Rows[0][0].ToCastInt64()\n\tif err != nil {\n\t\treturn settings, numTablesToCopy, err\n\t}\n\treturn settings, numTablesToCopy, nil\n}\n\nfunc (vr *vreplicator) setMessage(message string) (err error) {","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go#L500-L536","documentation":"readSettings loads the vreplication row settings (workflow type, filters, options) via binlogplayer.ReadVRSettings. When that read or parse fails, the error is wrapped with this message so operators know the VReplication engine could not load its configuration from _vt.vreplication. Without valid settings the vreplicator cannot start or configure itself.","triggerScenarios":"binlogplayer.ReadVRSettings returns an error, e.g. the query 'select ... from _vt.vreplication where id=<vr.id>' fails, the row is missing/corrupt, or settings fields (charset, options blob) fail to unmarshal.","commonSituations":"The _vt.vreplication row was manually edited or corrupted; the target tablet cannot reach MySQL; a schema migration of _vt.vreplication left the row in an unexpected shape; the workflow was deleted mid-flight while the vreplicator was loading.","solutions":["Check the wrapped cause (%v suffix) — it names the actual MySQL/query failure; run the settings query manually against _vt.vreplication for this vr.id.","Verify the _vt.vreplication row exists and its fields (source, message, options) are valid JSON/not corrupt.","Confirm MySQL connectivity from the tablet and that the _vt schema is present and at the expected version.","If the workflow is dead/garbage, delete the row with VReplicationExec or vtctldclient and re-create the workflow (MoveTables/Reshard)."],"exampleFix":"// before: row manually edited, options column is invalid JSON\n// after: recreate the workflow cleanly\n// vtctldclient MoveTables --target-keyspace=customer ...  (after cleaning the stale row)\n// DELETE FROM _vt.vreplication WHERE id=<bad_id>; -- via VReplicationExec, then re-run the workflow","handlingStrategy":"try-catch","validationCode":"// Before relying on the stream, check the settings row is readable and well-formed:\n// SELECT id, workflow, source, options FROM _vt.vreplication WHERE id = <id>;\n// Validate `options` parses as JSON if non-empty.","typeGuard":null,"tryCatchPattern":"err := vr.readSettings(ctx, dbClient)\nif err != nil {\n\tlog.Warn(\"vreplication settings unreadable; recreating workflow\", slog.Any(\"error\", err))\n\t// fall back to re-creating the workflow via vtctldclient\n}","preventionTips":["Never hand-edit _vt.vreplication rows; use vtctldclient workflows.","Ensure the target keyspace has the full _vt schema (run with proper init).","Monitor tablet logs for settings-read errors right after workflow creation.","Keep MySQL connectivity healthy between tablet and mysqld."],"tags":["vreplication","mysql","configuration"],"backgroundTag":"vreplication-settings-read-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}