thanos-io/thanos · error

no matching hashring to handle tenant

Error message

no matching hashring to handle tenant

What it means

multiHashring.GetN (via Get) failed to find any hashring in the multihashing configuration whose tenant list covers the requested tenant, so it returns this error and an empty Endpoint. It means the receive configuration partitions tenants across hashrings but the given tenant falls into no partition.

Solutions

  1. Add the tenant to the appropriate hashring's tenants list (or a catch-all '*' glob hashring) in the receive configuration
  2. Verify the exact tenant string sent by clients matches config casing/labels
  3. Ensure all receiver nodes share the same hashring config to avoid inconsistent routing
  4. If a default hashring is desired, add a final hashring with tenants: ['.*' or '*'] depending on matcher type

Example fix

// before
hashrings:
  - hashring: shard-0
    tenants: [tenant-a]
// after
hashrings:
  - hashring: shard-0
    tenants: [tenant-a]
  - hashring: default
    tenants: ['*']
Defensive patterns

Strategy: try-catch

Validate before calling

func tenantCovered(tenant string, rings []HashringConfig) bool {
    for _, r := range rings {
        for _, t := range r.Tenants {
            ok, _ := matchTenant(t, tenant)
            if ok { return true }
        }
    }
    return false
}

Try / catch

endpoint, err := hashring.Get(tenant)
if errors.Is(err, errNoMatchingHashring) {
    log.Warn("tenant not in any hashring, using default", "tenant", tenant)
    endpoint = fallbackEndpoint
}

Prevention

When it happens

Trigger: Calling Hasher/multiHashring Get/GetN with a tenant that matches none of the configured hashrings' tenant lists (each hashring matched via hashmod/glob/exact matchers).

Common situations: A tenant was created after the hashring config was written; tenant name typo in requests; tenants list intentionally excludes the tenant but the client still routes writes to it; config mismatch between querier and receiver.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/67cedd185314bba1. Report an issue: GitHub.

Appendix: source

Thrown at pkg/receive/hashring.go:345

			if mt, ok := t[tenant]; ok && isExactMatcher(mt) {
				found = true
			} else {
				var err error
				if found, err = t.match(tenant); err != nil {
					return Endpoint{}, err
				}
			}

		}
		if found {
			m.mu.Lock()
			m.cache[tenant] = m.hashrings[i]
			m.mu.Unlock()

			return m.hashrings[i].GetN(tenant, ts, n)
		}
	}
	return Endpoint{}, errors.New("no matching hashring to handle tenant")
}

func (m *multiHashring) Nodes() []Endpoint {
	return m.nodes
}

// shuffleShardHashring wraps a hashring implementation and applies shuffle sharding logic
// to limit which nodes are used for each tenant.
type shuffleShardHashring struct {
	baseRing Hashring

	shuffleShardingConfig ShuffleShardingConfig

	replicationFactor uint64

	nodes []Endpoint

	cache *lru.Cache[string, *ketamaHashring]

View on GitHub (pinned to 35b8b99117)