{"record":{"id":"506ed666a3a95132","repo":"thanos-io/thanos","slug":"s-tenant-not-found","errorCode":null,"errorMessage":"%s tenant not found","messagePattern":"(.+?) tenant not found","errorType":"http","errorClass":"ApiError","httpStatus":500,"severity":"error","filePath":"pkg/api/query/v1.go","lineNumber":1767,"sourceCode":"\t}\n\treq := &statuspb.TSDBStatisticsRequest{\n\t\tMatchers:                matchers,\n\t\tLimit:                   int32(limit),\n\t\tPartialResponseStrategy: ps,\n\t}\n\n\tvar stats map[string]*statuspb.TSDBStatisticsEntry\n\ttracing.DoInSpan(ctx, \"retrieve_tsdb_statistics\", func(ctx context.Context) {\n\t\tstats, warnings, err = qapi.status.TSDBStatistics(ctx, req)\n\t})\n\n\tif err != nil {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Wrap(err, \"retrieving tsdb statistics\")}, func() {}\n\t}\n\n\tif tenant != \"\" {\n\t\tif stats[tenant] == nil {\n\t\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Wrap(fmt.Errorf(\"%s tenant not found\", tenant), \"retrieving tsdb statistics\")}, func() {}\n\t\t}\n\n\t\treturn convertToTSDBSTatus(stats[tenant], limit), warnings.AsErrors(), nil, func() {}\n\t}\n\n\t// Merge statistics from all tenants.\n\taggregatedStats := &statuspb.TSDBStatisticsEntry{}\n\tfor _, v := range stats {\n\t\taggregatedStats.Merge(v)\n\t}\n\n\treturn convertToTSDBSTatus(aggregatedStats, limit), warnings.AsErrors(), nil, func() {}\n}\n\nfunc convertToTSDBSTatus(tsdbStatsEntry *statuspb.TSDBStatisticsEntry, limit int) *v1.TSDBStatus {\n\treturn &v1.TSDBStatus{\n\t\tHeadStats: v1.HeadStats{\n\t\t\tNumSeries:     tsdbStatsEntry.HeadStatistics.NumSeries,","sourceCodeStart":1749,"sourceCodeEnd":1785,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/api/query/v1.go#L1749-L1785","documentation":"When a `tenant` query param is provided, the response map from TSDBStatistics must contain an entry keyed by that tenant; if the map has no such key, this internal error (wrapped as '%s tenant not found') is returned.","triggerScenarios":"GET /api/v1/tsdb/status?tenant=foo where no store returned statistics for tenant 'foo' — the tenant does not exist, has an empty TSDB, or the request was served by stores that don't own that tenant's data.","commonSituations":"Typo in tenant name; querying against stores/route paths of a different tenant (multi-tenant setups); tenant with no data at query time; hitting a Thanos receive/querier that doesn't serve that tenant.","solutions":["Verify the tenant name matches exactly the tenant key reported in stats (case-sensitive).","Drop the tenant param to get merged statistics from all tenants and inspect available tenant keys.","Ensure the request reaches stores that actually hold the tenant's data (correct routing/sidecar/store-gateway config)."],"exampleFix":"// before\nGET /api/v1/tsdb/status?tenant=mytenant  // store has \"MyTenant\"\n// after\nGET /api/v1/tsdb/status  // inspect available tenants, then use exact key\nGET /api/v1/tsdb/status?tenant=MyTenant","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let data = await fetch(`${base}/api/v1/tsdb/status?tenant=${encodeURIComponent(tenant)}`).then(r => r.json());\nif (data.status === 'error' && /tenant not found/.test(data.error)) {\n  // fall back to merged stats to discover valid tenant keys\n  data = await fetch(`${base}/api/v1/tsdb/status`).then(r => r.json());\n}","preventionTips":["Fetch unfiltered stats once and cache the set of valid tenant keys.","Validate tenant names against known tenants before querying.","Remember tenant keys are case-sensitive and data-presence dependent."],"tags":["tenant","not-found","tsdb-status","multi-tenancy"],"backgroundTag":"record-not-found","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}