weaviate/weaviate · error
invalid tenant shard %q, expected %q
Error message
invalid tenant shard %q, expected %q
What it means
multiTenantRouter.validateTenantShard rejects a routing request where an explicit shard identifier does not match the tenant it was paired with. In multi-tenant collections each tenant owns exactly one shard, so shard names are derived from tenant names; passing both with different values indicates a caller bug or stale metadata. The check only fires when both values are non-empty.
Source
Thrown at cluster/router/router.go:662
orderedReplicas := sort(readReplicas.Replicas, preferredNode(params.DirectCandidateNode, r.nodeSelector.LocalName()))
return types.ReadRoutingPlan{
LocalHostname: r.nodeSelector.LocalName(),
Shard: params.Shard,
Tenant: params.Tenant,
ReplicaSet: types.ReadReplicaSet{
Replicas: orderedReplicas,
},
ConsistencyLevel: params.ConsistencyLevel,
IntConsistencyLevel: cl,
}, nil
}
// validateTenantShard validates that the tenant and shard are consistent.
func (r *multiTenantRouter) validateTenantShard(tenant, shard string) error {
if shard != "" && tenant != "" && shard != tenant {
return fmt.Errorf("invalid tenant shard %q, expected %q", shard, tenant)
}
return nil
}
// BuildRoutingPlanOptions constructs routing plan options for multi-tenant collections.
func (r *multiTenantRouter) BuildRoutingPlanOptions(tenant, shard string, cl types.ConsistencyLevel, directCandidate string) types.RoutingPlanBuildOptions {
return types.RoutingPlanBuildOptions{
Shard: shard,
Tenant: tenant,
ConsistencyLevel: cl,
DirectCandidateNode: directCandidate,
}
}
// tenantShard normalizes the shard parameter by using the tenant name as the shard
// if no explicit shard is provided, as required in multi-tenant mode.
func tenantShard(shard string, tenant string) string {View on GitHub (pinned to 75aa4b6d11)
Solutions
- Pass only the tenant and let the router resolve the shard itself (omit/empty the shard parameter).
- Verify the shard name equals the tenant name for multi-tenant collections; use the schema/tenants API to list correct tenant names.
- Refresh any cached tenant->shard mapping after tenant create/rename/delete operations.
Example fix
// before loc, err := router.GetReadWriteReplicasLocation(ctx, class, "tenant-1", "tenant-1_shard0", ...) // after loc, err := router.GetReadWriteReplicasLocation(ctx, class, "tenant-1", "", ...) // shard resolved from tenant
Defensive patterns
Strategy: validation
Validate before calling
func validateTenantShard(tenant, shard string) error {
if shard != "" && tenant != "" && shard != tenant {
return fmt.Errorf("shard %q does not match tenant %q", shard, tenant)
}
return nil
} Prevention
- Pass only the tenant for multi-tenant collections and let the router derive the shard.
- Never hand-build shard names; fetch tenants via the schema API.
- Invalidate cached tenant->shard mappings after tenant lifecycle operations.
When it happens
Trigger: Calling GetReadWriteReplicasLocation, GetWriteReplicasLocation, or GetReadReplicasLocation with a tenant and a shard string that differ, e.g. tenant="User-A" shard="User-B" or a hand-built shard name.
Common situations: Custom tooling that maps old shard names to tenants after a migration; clients caching a shard name from before a tenant rename; code concatenating collection/shard names incorrectly; replication scripts addressing shards directly.
Related errors
- class %s has multi-tenancy disabled, but request was with te
- role name uses a reserved operator prefix
- namespace is required
- user IDs on namespace-enabled clusters must be namespace-pre
- local %s shard does not exist
AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04).
Data as JSON: /api/errors/08cac9efa3cd4549.
Report an issue: GitHub.