thanos-io/thanos · error · ApiError

limit overflows int32

Error message

limit %d overflows int32

What it means

A range guard in the query API: the requested limit fits an int64 but exceeds math.MaxInt32, which is the widest limit the store API can carry in its protobuf fields. The request is rejected as bad data rather than silently truncating the limit.

Solutions

  1. Use a limit <= 2147483647
  2. Paginate queries instead of one huge limit

Example fix

// before
GET /api/v1/tsdb/status?limit=3000000000
// after
GET /api/v1/tsdb/status?limit=1000000
Defensive patterns

Strategy: validation

Validate before calling

function validTsdbLimit(n) { return Number.isInteger(n) && n >= 0 && n <= 2147483647; }

Prevention

When it happens

Trigger: GET /api/v1/tsdb/status?limit=3000000000 (any value > 2147483647) reaching the tsdbStatus handler.

Common situations: Users attempting 'practically unlimited' limits with huge numbers; script-generated limits from config files; confusion with int64-range limits accepted by other endpoints.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at pkg/api/query/v1.go:1748

	// Append tenant matcher when tenancy is enabled.
	var tenant string
	if qapi.enforceTenancy {
		tenant, err = tenancy.GetTenantFromHTTP(r, qapi.tenantHeader, qapi.defaultTenant, qapi.tenantCertField)
		if err != nil {
			return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
		}
		if tenant != "" {
			matchers = append(matchers, storepb.LabelMatcher{
				Type:  storepb.LabelMatcher_EQ,
				Name:  qapi.tenantLabel,
				Value: tenant,
			})
		}
	}

	if limit > math.MaxInt32 {
		return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf("limit %d overflows int32", limit)}, func() {}
	}
	req := &statuspb.TSDBStatisticsRequest{
		Matchers:                matchers,
		Limit:                   int32(limit),
		PartialResponseStrategy: ps,
	}

	var stats map[string]*statuspb.TSDBStatisticsEntry
	tracing.DoInSpan(ctx, "retrieve_tsdb_statistics", func(ctx context.Context) {
		stats, warnings, err = qapi.status.TSDBStatistics(ctx, req)
	})

	if err != nil {
		return nil, nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Wrap(err, "retrieving tsdb statistics")}, func() {}
	}

	if tenant != "" {
		if stats[tenant] == nil {

View on GitHub (pinned to 35b8b99117)