vitessio/vitess · error

no string value found for ENUM column %s in table %s -- with

Error message

no string value found for ENUM column %s in table %s -- with available values being: %v -- using the found integer value: %d

What it means

When decoding an ENUM value, the integer stored in the row is used as an index into the column's value map. If a non-zero integer has no corresponding string entry, the mapping is internally inconsistent (index 0 is reserved for the empty ENUM value), so vstreamer refuses to fabricate a value and returns this diagnostic listing the available mappings.

Source

Thrown at go/vt/vttablet/tabletserver/vstreamer/vstreamer.go:1452

		}
	}
	// ENUM columns are stored as an unsigned 16-bit integer as they can contain a maximum
	// of 65,535 elements (https://dev.mysql.com/doc/refman/en/enum.html) with the 0 element
	// reserved for any integer value that has no string mapping.
	iv, err := value.ToUint16()
	if err != nil {
		return sqltypes.Value{}, vterrors.Wrapf(err, "no valid integer value found for column %s in table %s, bytes: %b",
			plan.Table.Fields[colNum].Name, plan.Table.Name, iv)
	}
	var strVal string
	// Match the MySQL behavior of returning an empty string for invalid ENUM values.
	// This is what the 0 position in an ENUM is reserved for.
	if iv != 0 {
		var ok bool
		strVal, ok = plan.EnumSetValuesMap[colNum][int(iv)]
		if !ok {
			// The integer value was NOT 0 yet we found no mapping. This should never happen.
			return sqltypes.Value{}, fmt.Errorf("no string value found for ENUM column %s in table %s -- with available values being: %v -- using the found integer value: %d",
				plan.Table.Fields[colNum].Name, plan.Table.Name, plan.EnumSetValuesMap[colNum], iv)
		}
	}
	return sqltypes.MakeTrusted(plan.Table.Fields[colNum].Type, []byte(strVal)), nil
}

// buildSetStringValue takes the integer value of a SET column and returns the string value.
func buildSetStringValue(env *vtenv.Environment, plan *streamerPlan, colNum int, value sqltypes.Value) (sqltypes.Value, error) {
	if value.IsNull() { // No work is needed
		return value, nil
	}
	// Add the mappings just-in-time in case we haven't properly received and processed a
	// table map event to initialize it.
	if plan.EnumSetValuesMap == nil {
		if err := addEnumAndSetMappingstoPlan(env, plan.Plan, plan.Table.Fields, plan.TableMap.Metadata); err != nil {
			return sqltypes.Value{}, vterrors.Wrap(err, "failed to build SET column integer to string mappings")
		}
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Restore the original ENUM definition (same values, same order) so historical indexes map correctly
  2. Reload the table schema so EnumSetValuesMap is built from the correct ColumnType
  3. Use --track-schema-versions to decode with the schema version contemporaneous with the rows
  4. Re-copy or rewrite affected rows if the enum values were intentionally changed

Example fix

// before
ALTER TABLE t MODIFY c ENUM('b','c');
// after (restore order/values matching historical rows)
ALTER TABLE t MODIFY c ENUM('a','b','c');
Defensive patterns

Strategy: validation

Validate before calling

// Verify enum values match historical data:
// SHOW COLUMNS FROM <t> LIKE '<c>'; -- compare enum('...') list to what rows were written with

Try / catch

if strings.Contains(err.Error(), "no string value found for ENUM column") {
    // restore original enum ordering/values or decode with the matching schema version
}

Prevention

When it happens

Trigger: buildEnumStringValue looks up plan.EnumSetValuesMap[colNum][int(iv)] for iv != 0 and the key is missing, meaning the row's enum index exceeds the entries derived from the current ColumnType definition.

Common situations: The ENUM definition was shrunk or reordered after the row was written, so old row indexes don't match the current value list; schema cache with a truncated enum() list; corrupt/foreign row data.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/da058bb6f60614cc. Report an issue: GitHub.