{"record":{"id":"23adaaf4d3139713","repo":"vitessio/vitess","slug":"unsupported-function-v","errorCode":null,"errorMessage":"unsupported function: %v","messagePattern":"unsupported function: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletserver/vstreamer/planbuilder.go","lineNumber":834,"sourceCode":"\tif !ok {\n\t\treturn ColExpr{}, fmt.Errorf(\"unsupported: %v\", sqlparser.String(selExpr))\n\t}\n\tswitch inner := aliased.Expr.(type) {\n\tcase *sqlparser.ColName:\n\t\tif !inner.Qualifier.IsEmpty() {\n\t\t\treturn ColExpr{}, fmt.Errorf(\"unsupported qualifier for column: %v\", sqlparser.String(inner))\n\t\t}\n\t\tcolnum, err := findColumn(plan.Table, inner.Name)\n\t\tif err != nil {\n\t\t\treturn ColExpr{}, err\n\t\t}\n\t\treturn ColExpr{\n\t\t\tColNum: colnum,\n\t\t\tField:  plan.Table.Fields[colnum],\n\t\t}, nil\n\tcase sqlparser.AggrFunc:\n\t\tif inner.AggrName() != \"keyspace_id\" {\n\t\t\treturn ColExpr{}, fmt.Errorf(\"unsupported function: %v\", sqlparser.String(inner))\n\t\t}\n\t\tif len(inner.GetArgs()) != 0 {\n\t\t\treturn ColExpr{}, fmt.Errorf(\"unexpected: %v\", sqlparser.String(inner))\n\t\t}\n\t\tcv, err := vschema.FindColVindex(plan.Table.Name)\n\t\tif err != nil {\n\t\t\treturn ColExpr{}, err\n\t\t}\n\t\tvindexColumns, err := buildVindexColumns(plan.Table, cv.Columns)\n\t\tif err != nil {\n\t\t\treturn ColExpr{}, err\n\t\t}\n\t\treturn ColExpr{\n\t\t\tField: &querypb.Field{\n\t\t\t\tName:    \"keyspace_id\",\n\t\t\t\tType:    sqltypes.VarBinary,\n\t\t\t\tCharset: collations.CollationBinaryID,\n\t\t\t\tFlags:   uint32(querypb.MySqlFlag_BINARY_FLAG),","sourceCodeStart":816,"sourceCodeEnd":852,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go#L816-L852","documentation":"The vstreamer plan builder only supports a single aggregate function in a VStreamResults select expression: keyspace_id(). Any other aggregate (COUNT, SUM, MAX, etc.) cannot be computed incrementally from the binlog, so analyzeExpr rejects it with the full SQL text of the aggregate.","triggerScenarios":"Calling VStreamResults (or configuring a vstreamer select) with an expression like `select count(*) from t` or `select max(id) from t` — any sqlparser.AggrFunc whose AggrName() is not \"keyspace_id\".","commonSituations":"Writing a custom VReplication-style streaming query or materialization flow and accidentally adding a normal SQL aggregate; copying a MySQL query into a vstream select list expecting aggregation to work.","solutions":["Remove the aggregate from the select list; stream raw columns instead and aggregate client-side.","If you need the shard's keyspace_id, select only keyspace_id().","Use a VTGate query (not vstreamer) if you truly need server-side aggregation.","If you believe the aggregate should be supported, implement it in analyzeExpr's AggrFunc case of planbuilder.go."],"exampleFix":"// before\nselect count(*) from t\n// after\nselect keyspace_id() from t  -- or plain columns\nselect id, name from t","handlingStrategy":"validation","validationCode":"// Before calling VStreamResults, ensure every select expr is a plain column or keyspace_id()\nfunc validateVStreamSelect(exprs []string) error {\n    for _, e := range exprs {\n        if strings.ContainsAny(e, \"(*)\") && !strings.EqualFold(strings.TrimSpace(e), \"keyspace_id()\") {\n            return fmt.Errorf(\"aggregate %q not supported; use plain columns or keyspace_id()\", e)\n        }\n    }\n    return nil\n}","typeGuard":"func isSupportedAggregate(expr string) bool {\n    return strings.EqualFold(strings.TrimSpace(expr), \"keyspace_id()\")\n}","tryCatchPattern":"// Go: check the error from analyzeExpr at plan time\nif err := plan.AnalyzeExprs(vschema, selExprs); err != nil {\n    if strings.Contains(err.Error(), \"unsupported function\") {\n        return nil, fmt.Errorf(\"vstream select contains unsupported aggregate, revise select list: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Keep vstream select lists to plain columns or keyspace_id()","Aggregate client-side, never in a VStreamResults query","Review select lists generated by templates for accidental aggregates"],"tags":["vstreamer","vstream-results","unsupported-sql","aggregation"],"backgroundTag":"unsupported-vstream-expression","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}