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

  1. Pass only the tenant and let the router resolve the shard itself (omit/empty the shard parameter).
  2. Verify the shard name equals the tenant name for multi-tenant collections; use the schema/tenants API to list correct tenant names.
  3. 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

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


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/08cac9efa3cd4549. Report an issue: GitHub.