vitessio/vitess · error

conflicting entries: %q overlaps with %q

Error message

conflicting entries: %q overlaps with %q

What it means

When registering table ACL entries, tableacl builds a patricia trie of names/prefixes and rejects any new entry that overlaps an existing one (a name/prefix that is a prefix of another entry). Overlapping entries would give ambiguous ACL semantics.

Source

Thrown at go/vt/tableacl/tableacl.go:226

}

// ValidateProto returns an error if the given proto has problems
// that would cause InitFromProto to fail.
func ValidateProto(config *tableaclpb.Config) (err error) {
	t := patricia.NewTrie()
	for _, group := range config.TableGroups {
		for _, name := range group.TableNamesOrPrefixes {
			var prefix patricia.Prefix
			if before, ok := strings.CutSuffix(name, "%"); ok {
				prefix = []byte(before)
			} else {
				prefix = []byte(name + "\000")
			}
			if bytes.Contains(prefix, []byte("%")) {
				return fmt.Errorf("got: %s, '%%' means this entry is a prefix and should not appear in the middle of name or prefix", name)
			}
			overlapVisitor := func(_ patricia.Prefix, item patricia.Item) error {
				return fmt.Errorf("conflicting entries: %q overlaps with %q", name, item)
			}
			if err := t.VisitSubtree(prefix, overlapVisitor); err != nil {
				return err
			}
			if err := t.VisitPrefixes(prefix, overlapVisitor); err != nil {
				return err
			}
			t.Insert(prefix, name)
		}
	}
	return nil
}

// Authorized returns the list of entities who have the specified role on a tablel.
func Authorized(table string, role Role) *ACLResult {
	return currentTableACL.Authorized(table, role)
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Inspect the table ACL config and find the two overlapping entries named in the message
  2. Remove or rename one entry so no entry is a prefix of another
  3. Remember '%' is only allowed at the end (prefix entries); never put '%' mid-name
  4. Reload/restart vtgate or vttablet and confirm tableacl init succeeds

Example fix

// before
[{"name":"user%"},{"name":"users"}]
// after (disjoint)
[{"name":"user%"},{"name":"accounts"}]
Defensive patterns

Strategy: validation

Validate before calling

func validateACLEntries(names []string) error {
    for i, a := range names {
        if strings.Contains(strings.TrimSuffix(a, "%"), "%") {
            return fmt.Errorf("'%%' only allowed at end: %s", a)
        }
        for _, b := range names[i+1:] {
            if isPrefixOverlap(a, b) {
                return fmt.Errorf("overlap: %s vs %s", a, b)
            }
        }
    }
    return nil
}

Type guard

func isPrefixOnlyEntry(e string) bool {
    return strings.HasSuffix(e, "%") && !strings.Contains(strings.TrimSuffix(e, "%"), "%")
}

Try / catch

if err := tableacl.Init(config); err != nil {
    if strings.Contains(err.Error(), "conflicting entries") {
        return fmt.Errorf("fix table ACL config: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling tableacl initialization (RegisterACLTableEntries / config reload) with two table entries where one is a prefix of the other or one contains '%' as a mid-string wildcard (a separate '%' error is returned in that case); the overlapVisitor fails VisitSubtree/VisitPrefixes on the trie.

Common situations: TableACL config JSON (or queryserver-config-acl-table flags) listing both 'user%' and 'users', or a copy-paste of entries that prefix-overlap each other.

Related errors


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