vitessio/vitess · error

collision in caseInsensitiveTable

Error message

collision in caseInsensitiveTable

What it means

buildCaseInsensitiveTable builds an FNV-1a hash map from keyword name (lowercased) to keyword for case-insensitive SQL keyword lookup. It panics if two keyword entries produce the same FNV-1a hash, because the map could not distinguish them.

Source

Thrown at go/vt/sqlparser/keywords.go:856

	keywordVals    = map[string]int{}
)

// keywordLookupTable is a perfect hash map that maps **case insensitive** keyword names to their ids
var keywordLookupTable *caseInsensitiveTable

type caseInsensitiveTable struct {
	h map[uint64]keyword
}

func buildCaseInsensitiveTable(keywords []keyword) *caseInsensitiveTable {
	table := &caseInsensitiveTable{
		h: make(map[uint64]keyword, len(keywords)),
	}

	for _, kw := range keywords {
		hash := fnv1aIstr(offset64, kw.name)
		if _, exists := table.h[hash]; exists {
			panic("collision in caseInsensitiveTable")
		}
		table.h[hash] = kw
	}
	return table
}

func (cit *caseInsensitiveTable) LookupString(name string) (int, bool) {
	hash := fnv1aIstr(offset64, name)
	if candidate, ok := cit.h[hash]; ok {
		return candidate.id, candidate.matchStr(name)
	}
	return 0, false
}

func init() {
	for _, kw := range keywords {
		if kw.id == UNUSED {
			continue

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Find which two keyword entries collide by logging hash values in the loop before panicking
  2. Rename the newly added keyword or verify its spelling in the keywords table
  3. If the hash function was changed, re-verify collision-freedom or add a secondary key to disambiguate

Example fix

// before
{ /* duplicate-hashing keyword entry */ }
// after
{ /* keyword renamed so its fnv1aIstr hash is unique */ }
Defensive patterns

Strategy: validation

Validate before calling

seen := make(map[uint64]string)
for _, kw := range keywords {
    h := fnv1aIstr(offset64, kw.name)
    if prev, ok := seen[h]; ok {
        return fmt.Errorf("keyword %q collides with %q (hash %d)", kw.name, prev, h)
    }
    seen[h] = kw.name
}

Prevention

When it happens

Trigger: Adding a new entry to the `keywords` slice in keywords.go whose lowercased name hashes (via fnv1aIstr) to the same uint64 as an existing entry.

Common situations: Contributors adding new SQL keywords or reserved words during a SQL dialect/parser upgrade; a hand-edited keyword table where a name was typoed into colliding with an existing one.

Related errors


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