thanos-io/thanos · error

failed to unmarshal rulefmt.configRuleAdapter

Error message

failed to unmarshal rulefmt.configRuleAdapter

What it means

configRuleAdapter.UnmarshalYAML first decodes into the embedded rulefmt.RuleGroup and then re-unmarshals the raw node into a native map to preserve unknown fields. If that second pass fails, the YAML could not be represented as rulefmt.configRuleAdapter.

Solutions

  1. Validate the rules file with promtool check rules before applying
  2. Fix the field type reported by the nested YAML error (see the wrapped cause)
  3. Ensure 'interval', 'name', 'rules' fields follow the rulefmt.RuleGroup schema
  4. Pin matching Prometheus/Thanos versions if a field was renamed

Example fix

// before
interval: 30s
rules: "not-a-list"
// after
interval: 30s
rules:
  - alert: HighErrorRate
    expr: up == 0
    for: 5m
Defensive patterns

Strategy: validation

Validate before calling

// run before handing a file to the manager
groups, errs := rulefmt.ParseFile(file)
if len(errs) > 0 {
    return fmt.Errorf("invalid rule file %s: %v", file, errs)
}

Try / catch

var cg configRuleAdapter
if err := yaml.UnmarshalStrict(b, &cg); err != nil {
    var yerr *yaml.TypeError
    if errors.As(err, &yerr) {
        // report field-level type errors to the user
    }
    return errors.Wrap(err, "failed to unmarshal rulefmt.configRuleAdapter")
}

Prevention

When it happens

Trigger: A rule file contains YAML that does not match the Prometheus rule group schema: wrong field types (e.g. interval: "abc"), a scalar where a map is expected, or malformed structure for RuleGroup.

Common situations: Hand-edited rules file with a type error; version change where a field was renamed; passing a non-rule-group YAML file to the rules manager.

Related errors


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

Appendix: source

Thrown at pkg/rules/manager.go:233

	rs := struct {
		RuleGroup rulefmt.RuleGroup `yaml:",inline"`
		Strategy  string            `yaml:"partial_response_strategy"`
	}{}

	if err := unmarshal(&rs); err != nil {
		return err
	}

	g.PartialResponseStrategy = new(storepb.PartialResponseStrategy)
	// Same as YAMl. Quote as JSON unmarshal expects raw JSON field.
	if err := g.PartialResponseStrategy.UnmarshalJSON([]byte("\"" + rs.Strategy + "\"")); err != nil {
		return err
	}
	g.group = rs.RuleGroup

	var native map[string]any
	if err := unmarshal(&native); err != nil {
		return errors.Wrap(err, "failed to unmarshal rulefmt.configRuleAdapter")
	}
	delete(native, "partial_response_strategy")

	g.nativeRuleGroup = native
	return nil
}

func (g configRuleAdapter) MarshalYAML() (any, error) {
	return struct {
		RuleGroup map[string]any `yaml:",inline"`
	}{
		RuleGroup: g.nativeRuleGroup,
	}, nil
}

// TODO(bwplotka): Replace this with upstream implementation after https://github.com/prometheus/prometheus/issues/7128 is fixed.
func (g configRuleAdapter) validate() (errs []error) {
	set := map[string]struct{}{}

View on GitHub (pinned to 35b8b99117)