thanos-io/thanos · warning

not ready

Error message

not ready

What it means

The Status gRPC server's TSDB statistics getter returns errors.New("not ready") when the rule component's HTTP readiness probe (httpProbe.IsReady()) is still false. Any TSDBStats RPC issued before the component reports ready fails with this error instead of computing stats.

Solutions

  1. Wait for /-/ready to return OK, then retry the status request.
  2. If it persists, check logs for the underlying reason the probe is not ready (failed rule reload, TSDB issues).
  3. Add retry/backoff around status API calls in automation.
  4. Fix the failed reload (e.g. invalid rule file from error 139) so the component becomes ready.
Defensive patterns

Strategy: retry

Validate before calling

await fetch('http://rule:10902/-/ready').then(r => r.ok)

Try / catch

try { stats = await statusClient.TSDBStats(req) } catch (e) { if (String(e).includes('not ready')) { await waitForReady(); return retry() } throw e }

Prevention

When it happens

Trigger: A client calls the TSDB status/statistics RPC while the rule component is starting up or has been marked not ready (e.g. during a failed reload that set the probe unhealthy).

Common situations: Opening the Thanos UI/bucket status page right after pod restart; monitoring tooling polling the status API before readiness; component stuck not-ready due to a config reload failure.

Related errors


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

Appendix: source

Thrown at cmd/thanos/rule.go:793

						SupportsSharding:             true,
						SupportsWithoutReplicaLabels: true,
						TsdbInfos:                    tsdbStore.TSDBInfos(),
					}, nil
				}
				return nil, errors.New("Not ready")
			}),
			info.WithStatusInfoFunc(),
		)
		storeServer := store.NewLimitedStoreServer(store.NewInstrumentedStoreServer(reg, tsdbStore), reg, conf.storeRateLimits)
		options = append(options, grpcserver.WithServer(store.RegisterStoreServer(storeServer, logger)))

		// Add Status server for TSDB statistics
		statusSrv := status.NewServer(
			component.Rule.String(),
			status.WithTSDBStatisticsGetter(
				status.TSDBStatisticsGetterFunc(func(limit int, matchers []storepb.LabelMatcher) (map[string]tsdb.Stats, error) {
					if !httpProbe.IsReady() {
						return nil, errors.New("not ready")
					}

					// Check if external labels match the provided matchers.
					extLabels := conf.lset
					promMatchers, err := storepb.MatchersToPromMatchers(matchers...)
					if err != nil {
						return nil, errors.Wrap(err, "failed to convert matchers")
					}
					for _, matcher := range promMatchers {
						if !matcher.Matches(extLabels.Get(matcher.Name)) {
							// External labels don't match, return empty result.
							return nil, nil
						}
					}

					stats := tsdbDB.Head().Stats(labels.MetricName, limit)
					return map[string]tsdb.Stats{
						"": *stats,

View on GitHub (pinned to 35b8b99117)