vitessio/vitess · error
Invalid hint: %s, expected 3 characters
Error message
Invalid hint: %s, expected 3 characters
What it means
GenerateInternalTableName builds internal (_vt_...) table names as _vt_<hint>_<uuid>_<timestamp>_ and requires the hint to be exactly 3 characters, matching Vitess's internal naming convention. A shorter or longer hint makes the generated name unparseable by IsInternal*Table name parsers, so it is rejected up front.
Source
Thrown at go/vt/schema/name.go:103
}
func condenseUUID(uuid string) string {
uuid = strings.ReplaceAll(uuid, "-", "")
uuid = strings.ReplaceAll(uuid, "_", "")
return uuid
}
// isCondensedUUID answers 'true' when the given string is a condensed UUID, e.g.:
// a0638f6bec7b11ea9bf8000d3a9b8a9a
func isCondensedUUID(uuid string) bool {
return condensedUUIDRegexp.MatchString(uuid)
}
// generateGCTableName creates an internal table name, based on desired hint and time, and with optional preset UUID.
// If uuid is given, then it must be in condensed-UUID format. If empty, the function auto-generates a UUID.
func GenerateInternalTableName(hint string, uuid string, t time.Time) (tableName string, err error) {
if len(hint) != 3 {
return "", fmt.Errorf("Invalid hint: %s, expected 3 characters", hint)
}
if uuid == "" {
uuid, err = CreateUUIDWithDelimiter("")
} else {
uuid = condenseUUID(uuid)
}
if err != nil {
return "", err
}
if !isCondensedUUID(uuid) {
return "", fmt.Errorf("Invalid UUID: %s, expected condensed 32 hexadecimals", uuid)
}
timestamp := ToReadableTimestamp(t)
return fmt.Sprintf("_vt_%s_%s_%s_", hint, uuid, timestamp), nil
}
// IsInternalOperationTableName answers 'true' when the given table name stands for an internal Vitess
// table used for operations such as:View on GitHub (pinned to 01a25a7d17)
Solutions
- Pass exactly a 3-character hint, e.g. the GC state code like "rdg", "pur", "drp".
- Pad or map your desired label to a fixed 3-char code before calling.
- If the hint is user-provided, validate len(hint) == 3 in your own code first.
Example fix
// before
name, err := schema.GenerateInternalTableName("gcname", "", time.Now())
// after
name, err := schema.GenerateInternalTableName("gc_", "", time.Now()) // exactly 3 chars Defensive patterns
Strategy: validation
Validate before calling
if len(hint) != 3 {
return fmt.Errorf("hint must be 3 chars, got %q", hint)
} Try / catch
name, err := schema.GenerateInternalTableName(hint, uuid, now)
if err != nil {
return fmt.Errorf("cannot generate internal table name: %w", err)
} Prevention
- Use fixed 3-character constants for hints, never user input.
- Validate hint length at the boundary where the hint originates.
- Reuse existing GC state codes rather than inventing hints.
When it happens
Trigger: Calling schema.GenerateInternalTableName(hint, uuid, t) or generateGCTableName with a hint string whose len != 3, e.g. "gc" or "xyz0".
Common situations: Hand-written tooling or tests constructing GC table names with arbitrary hints; constants trimmed or truncated when passed through config; confusion between the 3-char GC state codes and full state names.
Related errors
- Invalid UUID: %s, expected condensed 32 hexadecimals
- BeforeSchema differs
- AfterSchema differs
- GetSchema(%v, nil, %v, %v) failed: %v
- VReplication streams must have named workflows for migration
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/2f6eea457734aa5f.
Report an issue: GitHub.