{"record":{"id":"5969ec3c0667492f","repo":"vitessio/vitess","slug":"cannot-update-immutable-column","errorCode":null,"errorMessage":"cannot update immutable column","messagePattern":"cannot update immutable column","errorType":"error_code","errorClass":"ErrCannotUpdateImmutableColumn","httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/workflow/vexec/query_planner.go","lineNumber":31,"sourceCode":"See the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage vexec\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"vitess.io/vitess/go/vt/sqlparser\"\n\t\"vitess.io/vitess/go/vt/vttablet/tmclient\"\n)\n\nvar ( // Query planning errors.\n\t// ErrCannotUpdateImmutableColumn is returned when attempting to plan a\n\t// query that updates a column that should be treated as immutable.\n\tErrCannotUpdateImmutableColumn = errors.New(\"cannot update immutable column\")\n\t// ErrUnsupportedQueryConstruct is returned when a particular query\n\t// construct is unsupported by a QueryPlanner, despite the more general kind\n\t// of query being supported.\n\t//\n\t// For example, VReplication supports DELETEs, but does not support DELETEs\n\t// with LIMIT clauses, so planning a \"DELETE ... LIMIT\" will return\n\t// ErrUnsupportedQueryConstruct rather than a \"CREATE TABLE\", which would\n\t// return an ErrUnsupportedQuery.\n\tErrUnsupportedQueryConstruct = errors.New(\"unsupported query construct\")\n)\n\n// Query execution errors.\n// ErrUnpreparedQuery is returned when attempting to execute an unprepared\n// QueryPlan.\nvar ErrUnpreparedQuery = errors.New(\"attempted to execute unprepared query\")\n\n// QueryPlanner defines the interface that VExec uses to build QueryPlans for\n// various vexec workflows. A given vexec table, which is to say a table in the","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/workflow/vexec/query_planner.go#L13-L49","documentation":"ErrCannotUpdateImmutableColumn is a sentinel error returned by the VReplication query planner (planUpdate) when an UPDATE statement targets a column that must never be mutated during vreplication vexec operations (e.g. identity/immutable bookkeeping columns). The planner refuses to build such a plan. Tests reference it directly, so it is part of the planner's public contract.","triggerScenarios":"Planning a VExec UPDATE against a _vt table whose plan (QueryPlanner.planUpdate) detects a SET clause on a column classified as immutable (e.g. a primary-key/identity column of the vreplication state tables).","commonSituations":"Hand-written VExec SQL via vtctldclient trying to patch vreplication rows' key columns, or tooling that generates UPDATE statements without excluding immutable columns.","solutions":["Remove the immutable column from the UPDATE's SET list and update only mutable columns","Insert a new row instead of mutating an immutable identity column","Use the intended workflow control path (MoveTablesComplete, Workflow Stop/Start) instead of raw UPDATEs on _vt tables"],"exampleFix":"// before\nUPDATE _vt.vreplication SET id = 2 WHERE id = 1\n// ErrCannotUpdateImmutableColumn\n// after\nUPDATE _tv.vreplication SET state = 'Running', message = '' WHERE id = 1","handlingStrategy":"type-guard","validationCode":"for _, col := range updateStmt.SetColumns() {\n    if immutableColumns[table.Contains(col)] {\n        return ErrCannotUpdateImmutableColumn\n    }\n}","typeGuard":"func isImmutableColumn(c sqlparser.ColName) bool {\n    return c.Metadata != nil && c.Metadata.IsIdentity\n}","tryCatchPattern":"err := planner.PlanUpdate(stmt)\nif errors.Is(err, workflow.ErrCannotUpdateImmutableColumn) {\n    return fmt.Errorf(\"rewrite UPDATE without setting immutable columns: %w\", err)\n}","preventionTips":["Never UPDATE identity/primary-key columns of _vt tables","Use workflow control commands instead of raw SQL on _vt.vreplication","Enumerate immutable columns in your tooling's allow-list of updatable columns"],"tags":["vreplication","vexec","query-planner"],"backgroundTag":"immutable-column-update","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}