weaviate/weaviate · warning
tenant '%s' not found when it should have been
Error message
tenant '%s' not found when it should have been
What it means
Weaviate's GET /v1/schema/{className}/tenants/{tenantName} handler fetched the tenant via GetConsistentTenant without error, but the returned tenant object was nil. Since the schema manager already maps genuinely missing tenants to a 404 (schemaUC.ErrNotFound), reaching this path means an unexpected nil result — an internal invariant violation rather than a normal 'not found' response. The handler returns 422 with this message to surface the inconsistency instead of nil-dereferencing.
Source
Thrown at adapters/handlers/rest/handlers_schema.go:630
return schema.NewTenantsGetOneNotFound()
}
if errors.Is(err, schemaUC.ErrUnexpectedMultiple) {
return schema.NewTenantsGetOneInternalServerError().
WithPayload(errPayloadFromSingleErr(principal, err))
}
switch {
case errors.As(err, &authzerrors.Forbidden{}):
return schema.NewTenantsGetOneForbidden().
WithPayload(errPayloadFromSingleErr(principal, err))
default:
return schema.NewTenantsGetOneUnprocessableEntity().
WithPayload(errPayloadFromSingleErr(principal, err))
}
}
if tenant == nil {
s.metricRequestsTotal.logUserError(params.ClassName)
return schema.NewTenantsGetOneUnprocessableEntity().
WithPayload(errPayloadFromSingleErr(principal, fmt.Errorf("tenant '%s' not found when it should have been", params.TenantName)))
}
s.metricRequestsTotal.logOk(params.ClassName)
return schema.NewTenantsGetOneOK().WithPayload(tenant)
}
func (s *schemaHandlers) tenantExists(params schema.TenantExistsParams, principal *models.Principal) middleware.Responder {
ctx := restCtx.AddPrincipalToContext(params.HTTPRequest.Context(), principal)
if err := s.manager.ConsistentTenantExists(ctx, principal, params.ClassName, *params.Consistency, params.TenantName); err != nil {
s.metricRequestsTotal.logError(params.ClassName, err)
if errors.Is(err, schemaUC.ErrNotFound) {
return schema.NewTenantExistsNotFound()
}
switch {
case errors.As(err, &authzerrors.Forbidden{}):
return schema.NewTenantExistsForbidden().
WithPayload(errPayloadFromSingleErr(principal, err))
default:
return schema.NewTenantExistsUnprocessableEntity().View on GitHub (pinned to 75aa4b6d11)
Solutions
- Retry the GET against the same or another node — a transient race typically resolves and either returns the tenant or a proper 404.
- Verify the tenant actually exists: GET /v1/schema/{class}/tenants and check the tenant name for exact case-sensitivity.
- Confirm cluster health and RAFT replication status; if the nil response is reproducible and stable, it is a bug — capture class name, tenant name, consistency level and node, and report it to weaviate/weaviate.
- If the tenant is genuinely gone (e.g. offloaded or deleted), re-create/activate it with POST /v1/schema/{class}/tenants before querying.
Example fix
// client: handle the unexpected 422 by re-listing tenants and retrying
// before
resp, err := client.Schema().TenantsGetter().WithClassName("Article").WithTenantName("tenant-1").Do(ctx)
if err != nil { return err } // assumes 404 is the only failure
// after
resp, err := client.Schema().TenantsGetter().WithClassName("Article").Do(ctx)
if err != nil { return err }
found := false
for _, t := range resp.Payload {
if t.Name == "tenant-1" { found = true; break }
}
if !found { return fmt.Errorf("tenant-1 does not exist; create or reactivate it first") }
// then retry the single-tenant GET Defensive patterns
Strategy: validation
Validate before calling
tenants, err := client.Schema().TenantsGetter().WithClassName("Article").Do(ctx)
if err != nil { return err }
exists := slices.ContainsFunc(tenants.Payload, func(t *models.Tenant) bool { return t.Name == "tenant-1" && t.Status != models.TenantStatusOffloaded })
if !exists { return fmt.Errorf("tenant-1 missing or offloaded") } Type guard
func tenantExists(tenants []*models.Tenant, name string) bool {
for _, t := range tenants {
if t != nil && t.Name == name { return true }
}
return false
} Try / catch
_, err := client.Schema().TenantGetter().WithClassName("Article").WithTenantName("tenant-1").Do(ctx)
var weaviateErr *fault.WeaviateClientError
if errors.As(err, &weaviateErr) && weaviateErr.StatusCode == 422 {
// unexpected nil tenant: list tenants and retry once
} Prevention
- Always list tenants (GET /schema/{class}/tenants) before fetching a single tenant in automated pipelines.
- Check tenant status (HOT/COLD/OFFLOADED) — offloaded tenants will not resolve.
- Treat a stable 422 'not found when it should have been' as a cluster-state bug; capture node + consistency level and report it.
- Retry once with the same consistency level before giving up to rule out transient replication lag.
When it happens
Trigger: Calling GET /v1/schema/{class}/tenants/{tenant} where GetConsistentTenant returns (nil, nil). This indicates a race (tenant removed between lookup and return) or a bug in the tenant-resolution path on the queried node, not a normal missing-tenant request (that yields 404).
Common situations: Hitting a node during a tenant offloading/deletion that is not yet reflected in its consistent view; multi-node clusters with replication lag or split state; bugs in RAFT-applied tenant state where the tenant record is logically absent but no error is propagated.
Related errors
- count tenants for limit check: %w
- role name uses a reserved operator prefix
- cannot create db user with root user name
- tenant is in a transitional state
- the given class is empty
AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04).
Data as JSON: /api/errors/90055160b516ba46.
Report an issue: GitHub.