vitessio/vitess · error
enum or set column %s does not have valid string values: %q;
Error message
enum or set column %s does not have valid string values: %q; the column's type definition is unavailable -- this usually means the column was dropped, and decoding historical rows for a dropped ENUM/SET column requires --track-schema-versions with a schema version retained from while the column still existed
What it means
To decode ENUM/SET values, vstreamer needs the string value list from the column's ColumnType (e.g. enum('a','b')). If the parentheses delimiting the value list are missing — meaning the type definition is unavailable, typically because the column was dropped — the historical row cannot be decoded and this actionable error is returned pointing to --track-schema-versions.
Source
Thrown at go/vt/vttablet/tabletserver/vstreamer/vstreamer.go:1408
// addEnumAndSetMappingstoPlan sets up any necessary ENUM and SET integer to string mappings.
func addEnumAndSetMappingstoPlan(env *vtenv.Environment, plan *Plan, cols []*querypb.Field, metadata []uint16) error {
plan.EnumSetValuesMap = make(map[int]map[int]string)
for i, col := range cols {
// If the column is a CHAR based type with a binary collation (e.g. utf8mb4_bin) then
// the actual column type is included in the second byte of the event metadata while
// the event's type for the field is BINARY. This is true for ENUM and SET types.
var mysqlType uint16
if sqltypes.IsQuoted(col.Type) {
mysqlType = metadata[i] >> 8
}
if col.Type == querypb.Type_ENUM || mysqlType == mysqlbinlog.TypeEnum ||
col.Type == querypb.Type_SET || mysqlType == mysqlbinlog.TypeSet {
// Strip the enum() / set() parts out.
begin := strings.Index(col.ColumnType, "(")
end := strings.LastIndex(col.ColumnType, ")")
if begin == -1 || end == -1 {
return fmt.Errorf("enum or set column %s does not have valid string values: %q; "+
"the column's type definition is unavailable -- this usually means the column "+
"was dropped, and decoding historical rows for a dropped ENUM/SET column "+
"requires --track-schema-versions with a schema version retained from while "+
"the column still existed", col.Name, col.ColumnType)
}
var err error
plan.EnumSetValuesMap[i], err = vtschema.ParseEnumOrSetTokensMap(env, col.ColumnType[begin+1:end])
if err != nil {
return err
}
}
}
return nil
}
// buildEnumStringValue takes the integer value of an ENUM column and returns the string value.
func buildEnumStringValue(env *vtenv.Environment, plan *streamerPlan, colNum int, value sqltypes.Value) (sqltypes.Value, error) {
if value.IsNull() { // No work is neededView on GitHub (pinned to 01a25a7d17)
Solutions
- Enable --track-schema-versions and retain the schema version captured while the ENUM/SET column still existed
- Restore the column (re-add it with the same definition) if the historical rows must be decoded
- Rebuild the table/re-copy data so old rows no longer need the dropped column's definition
- Skip or reposition the stream past events written before the column was dropped
Example fix
// before (vttablet flags) vttablet ... # no schema version tracking // after vttablet ... --track-schema-versions
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the column's type definition is retained: // SELECT column_type FROM information_schema.columns // WHERE table_name='<t>' AND column_name='<c>'; -- must contain enum(...)/set(...) // Enable --track-schema-versions on vttablet for historical decode.
Try / catch
if strings.Contains(err.Error(), "does not have valid string values") {
// enable/retain --track-schema-versions with the pre-DROP schema version, or skip past the dropped-column rows
} Prevention
- Enable --track-schema-versions before doing DDL on replicated tables
- Retain schema versions covering your vreplication retention window
- Avoid dropping ENUM/SET columns while historical streams are active
When it happens
Trigger: addEnumAndSetMappingstoPlan finds col.Type is ENUM or SET (or the binlog type is TypeEnum/TypeSet) but strings.Index/LastIndex of '(' and ')' in col.ColumnType return -1, so no value list can be extracted.
Common situations: Replaying old binlog rows for a table whose ENUM/SET column was since dropped; minimal schema (no full column types) cached for the table; missing --track-schema-versions history for the pre-DROP definition.
Related errors
- no string value found for ENUM column %s in table %s -- with
- VStreamer is not open
- only integer literals are supported
- only the integer literal 1 is supported
- VStreamer is not open
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/c57a189c4c11e11d.
Report an issue: GitHub.