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

  1. Retry the GET against the same or another node — a transient race typically resolves and either returns the tenant or a proper 404.
  2. Verify the tenant actually exists: GET /v1/schema/{class}/tenants and check the tenant name for exact case-sensitivity.
  3. 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.
  4. 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

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


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