{"record":{"id":"626840a73242705f","repo":"vitessio/vitess","slug":"vt13001-626840","errorCode":"VT13001","errorMessage":"no update expression for the target","messagePattern":"no update expression for the target","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/planbuilder/operators/update.go","lineNumber":244,"sourceCode":"\nfunc errIfDependentColumnUpdated(ctx *plancontext.PlanningContext, upd *sqlparser.Update, ueMap map[semantics.TableSet]updList) {\n\tfor _, ue := range upd.Exprs {\n\t\tfor _, list := range ueMap {\n\t\t\tfor _, dc := range list {\n\t\t\t\tfor _, bvExpr := range dc.jc.LHSExprs {\n\t\t\t\t\tif ctx.SemTable.EqualsExprWithDeps(ue.Name, bvExpr.Expr) {\n\t\t\t\t\t\tpanic(vterrors.VT12001(\n\t\t\t\t\t\t\tfmt.Sprintf(\"'%s' column referenced in update expression '%s' is itself updated\", sqlparser.String(ue.Name), sqlparser.String(dc.jc.Original))))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc createUpdateOpWithTarget(ctx *plancontext.PlanningContext, updStmt *sqlparser.Update, target semantics.TableSet, uList updList) dmlOp {\n\tif len(uList) == 0 {\n\t\tpanic(vterrors.VT13001(\"no update expression for the target\"))\n\t}\n\n\tti, err := ctx.SemTable.TableInfoFor(target)\n\tif err != nil {\n\t\tpanic(vterrors.VT13001(err.Error()))\n\t}\n\tvTbl := ti.GetVindexTable()\n\ttblName, err := ti.Name()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tvar leftComp sqlparser.ValTuple\n\tif len(vTbl.PrimaryKey) > 0 {\n\t\tleftComp = make(sqlparser.ValTuple, 0, len(vTbl.PrimaryKey))\n\t}\n\tcols := make([]*sqlparser.ColName, 0, len(vTbl.PrimaryKey))\n\tfor _, col := range vTbl.PrimaryKey {","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/planbuilder/operators/update.go#L226-L262","documentation":"VT13001 'no update expression for the target' is panicked in createUpdateOpWithTarget (go/vt/vtgate/planbuilder/operators/update.go:244), called from createUpdateWithInputOp. When planning an UPDATE against an explicit target table, the planner looks up the precomputed updList (SET assignments) for that target's TableSet; an empty list means no SET assignments were attributed to the target, so no update plan can be produced. This is an internal invariant violation: the statement parser should have guaranteed at least one expression per updated table.","triggerScenarios":"createUpdateOpWithTarget(ctx, updStmt, target, uList) is invoked with len(uList) == 0 — i.e. the updList map built by prepareUpdateExpressionList contains no entries for the specific target TableSet of a targetted UPDATE (UPDATE tbl, ... SET ... where assignments map to a different table than the one being planned).","commonSituations":"Multi-table UPDATE statements whose SET clause only assigns columns of tables other than the resolved target; planner confusion over table aliases or qualified vs unqualified SET columns; planner regressions after upgrades.","solutions":["Ensure the SET clause assigns at least one column of every table named in the UPDATE target (qualify columns explicitly, e.g. SET t1.a = ...)","Verify table aliases in the statement match those used in the SET clause","If the SET clause is correct, reduce the statement and file a Vitess bug — this is an internal planning error"],"exampleFix":"-- before (no assignment attributed to t2 target)\nUPDATE t1, t2 SET t1.a = 1 WHERE t1.id = t2.id;\n-- after (explicit per-table assignments)\nUPDATE t1, t2 SET t1.a = 1, t2.b = 2 WHERE t1.id = t2.id;","handlingStrategy":"validation","validationCode":"// ensure every table in the UPDATE target list has at least one SET assignment\nfor _, tbl := range updateTargets(stmt) { if !hasSetAssignmentFor(stmt, tbl) { return fmt.Errorf(\"no SET assignment for %s\", tbl) } }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"no update expression for the target\") {\n    return rewriteWithQualifiedSetColumns(ctx, stmt)\n}","preventionTips":["Qualify SET columns with the table alias (SET t1.a = ...) in multi-table updates","Include at least one assignment per table named in the UPDATE","Keep aliases consistent between the target list and the SET clause"],"tags":["vitess","planbuilder","update","internal-error","set-clause"],"backgroundTag":"update-missing-set-expression","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}