vitessio/vitess · error

too many values for set

Error message

too many values for set

What it means

evalSetBits converts a string to a SET bitmask by assigning one bit per element. MySQL limits SET columns to 64 elements; if the supplied EnumSetValues has more than 64 entries the function panics "too many values for set" as a safeguard against impossible schema state.

Source

Thrown at go/vt/vtgate/evalengine/eval_set.go:80

// the raw string using the binary collation. This ensures DISTINCT and other hash-based operations
// treat unknown sets as distinct based on their textual representation.
func (e *evalSet) Hash(h *vthash.Hasher) {
	// MySQL allows storing an empty set as an empty string, which yields set==0 and string=="";
	// unknown sets will have set==0 but non-empty string content.
	if e.set == 0 && e.string != "" {
		h.Write16(hashPrefixBytes)
		colldata.Lookup(collations.CollationBinaryID).Hash(h, hack.StringBytes(e.string), 0)
		return
	}
	h.Write16(hashPrefixIntegralPositive)
	h.Write64(e.set)
}

func evalSetBits(values *EnumSetValues, value string) uint64 {
	if values != nil && len(*values) > 64 {
		// This never would happen as MySQL limits SET
		// to 64 elements. Safeguard here just in case though.
		panic("too many values for set")
	}

	set := uint64(0)
	for val := range strings.SplitSeq(value, ",") {
		idx := valueIdx(values, val)
		if idx == -1 {
			continue
		}
		set |= 1 << idx
	}

	return set
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Fix the schema metadata so the SET column defines at most 64 elements
  2. In test/tooling code that builds EnumSetValues, cap at 64 values
  3. If you control the call site, validate len(*values) <= 64 before constructing the set

Example fix

// before
values := make([]string, 100) // invalid SET
// after
if len(values) > 64 {
    return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "SET supports at most 64 elements")
}
Defensive patterns

Strategy: validation

Validate before calling

if values != nil && len(*values) > 64 {
    return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "SET defines %d elements; max is 64", len(*values))
}

Type guard

func isValidSetValue(values *EnumSetValues) bool {
    return values == nil || len(*values) <= 64
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, "newEvalSet: %v", r)
    }
}()

Prevention

When it happens

Trigger: newEvalSet called with an *EnumSetValues containing >64 entries — i.e. schema metadata for a SET column with more than 64 members, which MySQL itself never produces.

Common situations: Corrupted or hand-edited schema metadata, a schemaloader bug, or tests constructing SET values artificially with more than 64 elements.

Related errors


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