{"record":{"id":"30ab5ae2b83913bc","repo":"vitessio/vitess","slug":"err-30ab5a","errorCode":null,"errorMessage":"err","messagePattern":"err","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/planbuilder/operators/update.go","lineNumber":254,"sourceCode":"\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 {\n\t\tcolName := sqlparser.NewColNameWithQualifier(col.String(), tblName)\n\t\tcols = append(cols, colName)\n\t\tleftComp = append(leftComp, colName)\n\t\tctx.SemTable.Recursive[colName] = target\n\t}\n\t// optimize for case when there is only single column on left hand side.\n\tvar lhs sqlparser.Expr = leftComp\n\tif len(leftComp) == 1 {\n\t\tlhs = leftComp[0]\n\t}","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/planbuilder/operators/update.go#L236-L272","documentation":"This is a raw `panic(err)` inside createUpdateOpWithTarget. After building the UPDATE operator, the planner re-resolves the target table info; if the semantic analysis cannot resolve the table for the update (ti.Name() failing), the internal error is re-raised as a panic. Vitess converts planner panics into VTGate internal errors, so the user sees the underlying resolution failure message.","triggerScenarios":"Running an UPDATE whose target table expression cannot be resolved by the semantic table during plan building — e.g. the table info lookup or ti.Name() fails for a derived/aliased target in createUpdateOpWithTarget.","commonSituations":"Updating through an alias or derived table expression that the planner's table resolution does not support; corrupt or unusual vindex metadata on the target; planner bugs reached via unusual UPDATE syntax.","solutions":["Rewrite the UPDATE to target a real, unambiguous table name (no derived-table targets).","Check the table's vindex configuration in the keyspace routing rules / vschema for errors.","If it persists, file a Vitess bug with the query and vschema; this panic signals an unsupported or buggy path.","Check for missing or misnamed tables in the vschema (table not defined where expected)."],"exampleFix":"// before\nUPDATE (SELECT id FROM t) AS x SET name = 'a';\n// after\nUPDATE t SET name = 'a' WHERE id IN (SELECT id FROM t);","handlingStrategy":"validation","validationCode":"// Ensure the UPDATE targets a real, routable base table\nif !isBaseTable(updateTarget) {\n  return errors.New(\"UPDATE must target a real base table known to the vschema\")\n}","typeGuard":null,"tryCatchPattern":"// Vitess converts the panic to an internal error on the RPC\nres, err := vtgate.Execute(ctx, session, query, vars)\nif isInternalError(err) { log.Error(err); return fallbackPlan() }","preventionTips":["Always UPDATE base tables, never derived tables or inline views","Keep the vschema in sync with the MySQL schema","Test UPDATE statements against the Vitess planner before deploying them in app code"],"tags":["vitess","planbuilder","internal-panic","table-resolution"],"backgroundTag":"planner-internal-error","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}