thanos-io/thanos · error

parse limit configuration

Error message

parse limit configuration

What it means

ParseLimitConfigContent wraps failures of ParseRootLimitConfig — parsing the YAML bytes into RootLimitsConfig — with 'parse limit configuration'. The content was read successfully but is not valid YAML or does not match the expected limit config schema.

Solutions

  1. Read the wrapped error for the exact YAML line/column or field that failed validation
  2. Run the file through a YAML linter and fix syntax (indentation, tabs, stray characters)
  3. Compare fields against the current RootLimitsConfig schema for the binary version; remove/rename obsolete keys
  4. Render/resolve any templating before loading so raw placeholders don't reach the parser
  5. Add a CI check that parses the limits config with ParseRootLimitConfig before deployment

Example fix

// before
tenants:
  tenant-a:
    max_head_series: "abc"   # string, expected int
// after
tenants:
  tenant-a:
    max_head_series: 1000000
Defensive patterns

Strategy: validation

Validate before calling

func validateLimitsYAML(data []byte) error {
    var raw map[string]interface{}
    if err := yaml.Unmarshal(data, &raw); err != nil {
        return fmt.Errorf("limits YAML invalid: %w", err)
    }
    return nil
}

Try / catch

cfg, err := receive.ParseLimitConfigContent(content)
if err != nil {
    return nil, fmt.Errorf("check limits file YAML and field names: %w", err)
}

Prevention

When it happens

Trigger: Calling ParseLimitConfigContent with content that fails ParseRootLimitConfig: invalid YAML syntax, wrong types for limit fields (e.g. string where int expected), or unknown/invalid schema fields when strict parsing is on.

Common situations: Hand-edited YAML with bad indentation or tabs; schema drift after upgrading (renamed limit fields); pasting JSON into a strict YAML parser path; template variables left unresolved in the file.

Related errors


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

Appendix: source

Thrown at pkg/receive/limiter.go:209

func (l *Limiter) WriteGate() gate.Gate {
	l.RLock()
	defer l.RUnlock()
	return l.writeGate
}

// ParseLimitConfigContent parses the limit configuration from the path or
// content.
func ParseLimitConfigContent(limitsConfig fileContent) (*RootLimitsConfig, error) {
	if limitsConfig == nil {
		return &RootLimitsConfig{}, nil
	}
	limitsContentYaml, err := limitsConfig.Content()
	if err != nil {
		return nil, errors.Wrap(err, "get content of limit configuration")
	}
	parsedConfig, err := ParseRootLimitConfig(limitsContentYaml)
	if err != nil {
		return nil, errors.Wrap(err, "parse limit configuration")
	}
	return parsedConfig, nil
}

View on GitHub (pinned to 35b8b99117)