vitessio/vitess · error
VT03015
VT03015
Error message
column has duplicate set values: '%v'
What it means
The SET clause of an UPDATE assigns a value to the same vindex column more than once (e.g. SET vcol = 1, vcol = 2). Vitess cannot evaluate a single value for the vindex mapping, so it panics with VT03015 reporting the duplicated column.
Source
Thrown at go/vt/vtgate/planbuilder/operators/update.go:1127
return selExprs, offset
}
func createAssignmentExpressions(
ctx *plancontext.PlanningContext,
assignments []SetExpr,
vcol sqlparser.IdentifierCI,
subQueriesArgOnChangedVindex []string,
vindexValueMap map[string]evalengine.Expr,
compExprs []sqlparser.Expr,
) ([]string, []sqlparser.Expr) {
// Searching in order of columns in colvindex.
found := false
for _, assignment := range assignments {
if !vcol.Equal(assignment.Name.Name) {
continue
}
if found {
panic(vterrors.VT03015(assignment.Name.Name))
}
found = true
pv, err := evalengine.Translate(assignment.Expr.EvalExpr, &evalengine.Config{
ResolveType: ctx.TypeForExpr,
Collation: ctx.SemTable.Collation,
Environment: ctx.VSchema.Environment(),
})
if err != nil {
panic(invalidUpdateExpr(assignment.Name.Name.String(), assignment.Expr.EvalExpr))
}
if assignment.Expr.Info != nil {
sqe, ok := assignment.Expr.Info.(SubQueryExpression)
if ok {
for _, sq := range sqe {
subQueriesArgOnChangedVindex = append(subQueriesArgOnChangedVindex, sq.ArgName)
}
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Remove duplicate assignments so each vindex column appears at most once in SET
- Deduplicate SET clauses when building SQL dynamically
- Last assignment wins in MySQL, so keep only the final intended assignment
Example fix
// before UPDATE t SET vk = 1, vk = 2 WHERE id = 3; // after UPDATE t SET vk = 2 WHERE id = 3;
Defensive patterns
Strategy: validation
Validate before calling
// deduplicate SET targets before executing
seen := map[string]bool{}
for _, a := range stmt.Exprs {
name := a.Name.Name.String()
if seen[name] {
return fmt.Errorf("duplicate SET assignment for %s", name)
}
seen[name] = true
} Try / catch
if err != nil && strings.Contains(err.Error(), "duplicate set values") {
// rebuild the UPDATE with deduplicated SET clause
} Prevention
- Deduplicate SET clauses when constructing SQL dynamically
- Configure ORMs to emit one assignment per changed column
- Lint generated SQL for duplicate assignments in tests
When it happens
Trigger: createAssignmentExpressions finds two assignments for the same virtual/vindex column while iterating the UPDATE's assignments.
Common situations: Dynamically generated UPDATE statements appending SET clauses; ORMs concatenating partial updates; hand-written SQL with accidental duplicate assignments.
Related errors
- lookup.Update.convert: %v
- invalidUpdateExpr(...)
- VT03014
- no sharded vschema was provided, so you will need to update
- Binary.ReverseMap: keyspaceId is nil
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/73561644dec7ea6e.
Report an issue: GitHub.