t8y2/dbx · error

ambiguous Vastbase relation name %s.%s under case-insensitiv

Error message

ambiguous Vastbase relation name %s.%s under case-insensitive matching

What it means

After case-insensitive matching, if more than one relation matches the given schema.table and none matches exactly, the driver refuses to guess and returns this ambiguity error. This happens when e.g. both "users" and "Users" exist as distinct quoted identifiers in the same schema.

Source

Thrown at agents/drivers/vastbase-go/vastbase_metadata.go:1676

	matches := []relationName{}
	for rows.Next() {
		var match relationName
		if err := rows.Scan(&match.schema, &match.table); err != nil {
			return "", "", err
		}
		matches = append(matches, match)
	}
	if err := rows.Err(); err != nil {
		return "", "", err
	}
	if len(matches) == 0 {
		return "", "", fmt.Errorf("Vastbase relation not found: %s.%s", schema, table)
	}
	if matches[0].schema == schema && matches[0].table == table {
		return schema, table, nil
	}
	if len(matches) > 1 {
		return "", "", fmt.Errorf("ambiguous Vastbase relation name %s.%s under case-insensitive matching", schema, table)
	}
	return matches[0].schema, matches[0].table, nil
}

func (s *server) relationAttributesByNumber(catalog, prefix, schema, table string) (map[int]string, error) {
	query := fmt.Sprintf(`SELECT a.attnum, a.attname
FROM %s.%s_attribute a JOIN %s.%s_class c ON c.oid = a.attrelid
JOIN %s.%s_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = %s AND c.relname = %s AND a.attnum > 0 AND NOT a.attisdropped`, catalog, prefix, catalog, prefix, catalog, prefix, quoteLiteral(schema), quoteLiteral(table))
	rows, err := s.metadataQuery(query)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	result := map[int]string{}
	for rows.Next() {
		var number int
		var name string

View on GitHub (pinned to c0390bff16)

Solutions

  1. Pass the exact case of the intended relation so the exact-match branch resolves it unambiguously.
  2. Rename one of the duplicate-cased relations (e.g. ALTER TABLE "Orders" RENAME TO orders_legacy).
  3. Query the catalog to list the case-insensitive matches and pick the intended one explicitly.
  4. Avoid creating tables differing only by identifier case.

Example fix

// before
// schema has both `users` and "Users"
cols, err := srv.ListColumns("public", "USERS")
// ambiguous Vastbase relation name public.USERS under case-insensitive matching

// after
cols, err := srv.ListColumns("public", "Users") // exact match resolves
Defensive patterns

Strategy: validation

Validate before calling

var matches int
err := db.QueryRow(`SELECT COUNT(*) FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace WHERE n.nspname=$1 AND lower(c.relname)=lower($2)`, schema, table).Scan(&matches)
if matches > 1 {
    return fmt.Errorf("%d case-insensitive matches for %s.%s — pass exact case", matches, schema, table)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "ambiguous Vastbase relation") {
    // resolve manually: query pg_class for all case variants and pick exact one
    return resolveManually(schema, table)
}

Prevention

When it happens

Trigger: Passing a name whose case differs from any existing relation while at least two case-insensitive matches exist — e.g. schema contains both `orders` and `Orders` and the caller asks for 'ORDERS'.

Common situations: Schemas where quoted mixed-case and lowercase tables with the same spelling coexist (common after migrations from case-sensitive systems); automated tooling creating duplicate-cased names.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/9422ed5f3a21ca12. Report an issue: GitHub.