thanos-io/thanos · error
parsing config YAML file
Error message
parsing config YAML file
What it means
ParseRootLimitConfig reads a root limit-config YAML file and unmarshals it with yaml.UnmarshalStrict. This error wraps any YAML parsing or schema-mismatch failure, so the original yaml error (with line/column info) is preserved underneath. UnmarshalStrict means unknown fields in the file also trigger it.
Solutions
- Check the wrapped yaml error in the error chain for the exact line/column and fix the YAML syntax
- Remove or correct unknown fields — UnmarshalStrict rejects fields not present in RootLimitsConfig
- Validate types: e.g. max_connection or limit fields must be integers, not strings
- Run the file through a YAML linter and confirm top-level structure is writeLimits (with globalLimits etc.)
- Verify the file mounted/passed to the component is the intended config (not a secret manifest or empty file)
Example fix
// before (invalid: unknown key + bad type)
writeLimits:
globalLimit:
max_head_series: "100000"
// after
writeLimits:
globalLimits:
maxHeadSeries: 100000 Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-validate YAML before calling ParseRootLimitConfig
if len(content) == 0 { return errors.New("limits config is empty") }
var probe map[string]interface{}
if err := yaml.Unmarshal(content, &probe); err != nil {
return fmt.Errorf("invalid YAML: %w", err)
}
_, ok := probe["writeLimits"]
if !ok { return errors.New("missing writeLimits section") } Type guard
func hasKnownKeys(root map[string]interface{}) bool {
for k := range root {
if k != "writeLimits" { return false }
}
return true
} Try / catch
cfg, err := ParseRootLimitConfig(content)
if err != nil {
var yErr yaml.TypeError
if errors.As(err, &yErr) { log.Fatalf("config schema error: %v", err) }
return fmt.Errorf("loading limits config: %w", err)
} Prevention
- Lint the limits YAML in CI with a schema validator (kubeconform-style or yamllint + schema)
- Pin a config template and review all field names against RootLimitsConfig
- Test config load at deploy time with a canary before rollout
- Beware UnmarshalStrict: any unknown key is fatal
When it happens
Trigger: Calling ParseRootLimitConfig (or ParseLimitConfigContent, or runReceive when loading --receive.limits-config) with malformed YAML, wrong indentation/types, or unknown top-level fields since strict unmarshaling is used.
Common situations: Hand-edited limits config files with bad indentation; typos in field names like 'writelimts'; passing JSON where YAML is expected with tabs; kubernetes secret mounted config containing stray whitespace or an old schema no longer recognized after a Thanos upgrade.
Related errors
- unable to unmarshal config content
- parsing downstream tripper config YAML file
- parsing downstream tripper TLS config YAML
- initializing the query range cache config
- initializing the labels cache config
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/8c9a55dd151a8ff3.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/receive/limiter_config.go:26
"gopkg.in/yaml.v2"
"github.com/thanos-io/thanos/pkg/clientconfig"
"github.com/thanos-io/thanos/pkg/errors"
)
// RootLimitsConfig is the root configuration for limits.
type RootLimitsConfig struct {
// WriteLimits hold the limits for writing data.
WriteLimits WriteLimitsConfig `yaml:"write"`
}
// ParseRootLimitConfig parses the root limit configuration. Even though
// the result is a pointer, it will only be nil if an error is returned.
func ParseRootLimitConfig(content []byte) (*RootLimitsConfig, error) {
var root RootLimitsConfig
if err := yaml.UnmarshalStrict(content, &root); err != nil {
return nil, errors.Wrapf(err, "parsing config YAML file")
}
if root.WriteLimits.GlobalLimits.MetaMonitoringURL != "" {
u, err := url.Parse(root.WriteLimits.GlobalLimits.MetaMonitoringURL)
if err != nil {
return nil, errors.Wrapf(err, "parsing meta-monitoring URL")
}
// url.Parse might pass a URL with only path, so need to check here for scheme and host.
// As per docs: https://pkg.go.dev/net/url#Parse.
if u.Host == "" || u.Scheme == "" {
return nil, errors.Newf("%s is not a valid meta-monitoring URL (scheme: %s,host: %s)", u, u.Scheme, u.Host)
}
root.WriteLimits.GlobalLimits.metaMonitoringURL = u
}
// Set default query if none specified.
if root.WriteLimits.GlobalLimits.MetaMonitoringLimitQuery == "" {View on GitHub (pinned to 35b8b99117)