vitessio/vitess · warning · ErrAmbiguousSchema
%w: %d schemas found with table named %s
Error message
%w: %d schemas found with table named %s
What it means
VTAdmin's FindSchema RPC searches all clusters for schemas containing the requested table; when the table is found in more than one distinct schema it refuses to guess and returns errors.ErrAmbiguousSchema wrapped with the match count and table name. This protects callers from silently acting on the wrong keyspace/table definition. Exactly one match returns that schema; zero matches are handled earlier in the switch.
Source
Thrown at go/vt/vtadmin/api.go:788
}(c)
}
wg.Wait()
if rec.HasErrors() {
return nil, rec.Error()
}
switch len(results) {
case 0:
return nil, &errors.NoSuchSchema{
Clusters: clusterIDs,
Table: req.Table,
}
case 1:
return results[0], nil
default:
return nil, fmt.Errorf("%w: %d schemas found with table named %s", errors.ErrAmbiguousSchema, len(results), req.Table)
}
}
// GetBackups is part of the vtadminpb.VTAdminServer interface.
func (api *API) GetBackups(ctx context.Context, req *vtadminpb.GetBackupsRequest) (*vtadminpb.GetBackupsResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.GetBackups")
defer span.Finish()
clusters, _ := api.getClustersForRequest(req.ClusterIds)
var (
m sync.Mutex
wg sync.WaitGroup
rec concurrency.AllErrorRecorder
backups []*vtadminpb.ClusterBackup
)
if req.RequestOptions == nil {View on GitHub (pinned to 01a25a7d17)
Solutions
- Narrow the request to a single cluster by setting Clusters in the FindSchema request (or the cluster_ids query param)
- Use a more specific table name, including keyspace qualification if the API path supports it
- If the ambiguity is a real duplicate, pick the intended cluster and query its schema directly via GetSchema
Example fix
// before GET /api/schema?table=users // after GET /api/schema?table=users&cluster_ids=commerce
Defensive patterns
Strategy: try-catch
Validate before calling
const matches = await Promise.all(clusterIds.map(c => getSchema(c, table).catch(() => null)));
const found = matches.filter(Boolean);
if (found.length > 1) {
throw new Error('table ' + table + ' exists in ' + found.length + ' clusters; narrow with cluster_ids');
} Type guard
function isAmbiguousSchema(err: unknown): boolean {
return err instanceof Error && err.message.includes('schemas found with table named');
} Try / catch
try {
schema = await findSchema(table, clusterIds);
} catch (err) {
if (isAmbiguousSchema(err)) {
const n = parseInt(err.message, 10);
schema = await findSchema(table, [preferredCluster]);
} else {
throw err;
}
} Prevention
- Always pass cluster_ids to FindSchema in multi-cluster deployments
- Avoid relying on table-name uniqueness across clusters; qualify with cluster or keyspace
- Adopt distinct naming conventions for environment-specific tables
When it happens
Trigger: Calling FindSchema (GET /schema?table=users) where the table name exists in schemas of 2+ clusters (per the request's cluster filter) so the default case (len(results) > 1) is hit.
Common situations: Multi-cluster setups where the same table name (e.g. 'users') is deployed in several keyspaces/clusters; calling without narrowing Clusters in the request; shared table naming conventions across environments.
Related errors
- not allowed: deny-all security-policy enforced
- ReloadSchemas(cluster = %s) failed: %w
- GetSchema(%s): %w
- ErrNoTablet
- opts %+v, err: %w
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/9280844c01dcbb3c.
Report an issue: GitHub.