weaviate/weaviate · critical

NAMESPACES_ENABLED=false but cluster has %d namespace-qualif

Error message

NAMESPACES_ENABLED=false but cluster has %d namespace-qualified role permission(s) (e.g. %q); refusing to start with inconsistent state

What it means

With NAMESPACES_ENABLED=false, the startup check inspects stored policy resources (what role permissions grant access to) and aborts if any contain a namespace qualifier ':' — except opaque ID resources like users/<id> or groups/<type>/<name>, whose colons may belong to the ID itself and are deliberately skipped. The guard exists because qualified permission resources would be misinterpreted with namespaces off.

Source

Thrown at adapters/handlers/rest/configure_api.go:1317

		// Guards against disabling namespaces on a namespaced cluster.
		return fmt.Errorf("NAMESPACES_ENABLED=false but cluster has %d namespace-qualified collection(s) (e.g. %q); refusing to start with inconsistent state", namespacedCount, namespacedExample)
	}

	// Role names, policy resources (what a role's permissions grant access to)
	// and grouping subjects (who a role assignment binds) may each be
	// namespace-qualified when NAMESPACES_ENABLED=true. With namespaces disabled
	// they would be misinterpreted, so the rows are only inspected in that case.
	if !enabled {
		if n, ex := countQualified(roleNames, conv.ContainsNamespaceSeparator); n > 0 {
			return fmt.Errorf("NAMESPACES_ENABLED=false but cluster has %d namespace-qualified role(s) (e.g. %q); refusing to start with inconsistent state", n, ex)
		}
		// A users/<id> or groups/<type>/<name> resource may carry a ':' inside the
		// id itself (e.g. an OIDC username), so its colon is not a namespace
		// qualifier and the resource is skipped; collection/role shapes still count.
		if n, ex := countQualified(policyResources, func(r string) bool {
			return !conv.IsOpaqueIDResource(r) && conv.ContainsNamespaceSeparator(r)
		}); n > 0 {
			return fmt.Errorf("NAMESPACES_ENABLED=false but cluster has %d namespace-qualified role permission(s) (e.g. %q); refusing to start with inconsistent state", n, ex)
		}
		// Only a colon in a direct db user (e.g. db:customer1:alice) is a namespace
		// qualifier — db names forbid ':'. OIDC names may contain ':', so oidc:
		// subjects are ambiguous and skipped; groups are global regardless of name.
		if n, ex := countQualified(groupingSubjects, func(s string) bool {
			user, prefix, err := conv.GetUserAndPrefix(s)
			if err != nil || prefix != string(authentication.AuthTypeDb) {
				return false
			}
			return conv.ContainsNamespaceSeparator(user)
		}); n > 0 {
			return fmt.Errorf("NAMESPACES_ENABLED=false but cluster has %d role assignment(s) to a namespace-qualified principal (e.g. %q); refusing to start with inconsistent state", n, ex)
		}
	}
	return nil
}

// countQualified returns how many values satisfy isQualified and the first such

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Restart with NAMESPACES_ENABLED=true to interpret the qualified permission resources.
  2. Revoke or rewrite the offending role permissions (remove 'ns:'-qualified resources) while namespaces are enabled, then boot with the flag off.
  3. Start from a clean meta-store if the permissions are disposable.
Defensive patterns

Strategy: validation

Validate before calling

// scan policy resources for namespace qualifiers, skipping opaque IDs (users/<id>, groups/<type>/<name>)
for _, res := range listPolicyResources() {
  if isOpaqueIDResource(res) { continue }
  if strings.Contains(res, ":") {
    return fmt.Errorf("permission resource %q is namespace-qualified; keep NAMESPACES_ENABLED=true", res)
  }
}

Prevention

When it happens

Trigger: Boot with NAMESPACES_ENABLED=false while the RBAC store holds permissions targeting namespace-qualified resources (e.g. collections like 'ns1:Article'); opaque-ID resources are ignored, plain qualified resources trigger the error.

Common situations: Rolling back NAMESPACES_ENABLED after permissions were granted against namespaced collections; restoring a namespaced RBAC backup onto a non-namespaced node; copying authorization state between differently configured clusters.

Related errors


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