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

  1. Pass exactly a 3-character hint, e.g. the GC state code like "rdg", "pur", "drp".
  2. Pad or map your desired label to a fixed 3-char code before calling.
  3. 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

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


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