thanos-io/thanos · error

: failed to marshal rule groups

Error message

%s: failed to marshal rule groups

What it means

Raised in Manager.Update while re-serializing each parsed rule group file back to YAML, grouped by partial-response strategy, into the manager's workDir. It fires when yaml.Marshal of a strategy's configGroups fails, which is unexpected since the groups were just unmarshaled successfully; it indicates a serialization defect or unsupported field content, and that strategy's rule file is skipped.

Solutions

  1. Check the rule group content for fields that fail YAML marshaling
  2. Update Thanos/Prometheus rule config structs if a newly supported field is not marshalable
  3. Inspect the wrapped yaml.Marshal error to identify the offending field
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at pkg/rules/manager.go:364 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at pkg/rules/manager.go:364

			continue
		}

		var rg configGroups
		if err := yaml.Unmarshal(b, &rg); err != nil {
			errs.Add(errors.Wrap(err, fn))
			continue
		}

		// NOTE: This is very ugly, but we need to write those yaml into tmp dir without the partial partial response field
		// which is not supported, to be able to reuse rules.Manager. The problem is that it uses yaml.UnmarshalStrict.
		groupsByStrategy := map[storepb.PartialResponseStrategy][]configRuleAdapter{}
		for _, rg := range rg.Groups {
			groupsByStrategy[*rg.PartialResponseStrategy] = append(groupsByStrategy[*rg.PartialResponseStrategy], rg)
		}
		for s, rg := range groupsByStrategy {
			b, err := yaml.Marshal(configGroups{Groups: rg})
			if err != nil {
				errs = append(errs, errors.Wrapf(err, "%s: failed to marshal rule groups", fn))
				continue
			}

			// Use full file name appending to work dir, so we can differentiate between different dirs and same filenames(!).
			// This will be also used as key for file group name.
			newFn := filepath.Join(m.workDir, s.String(), fn)
			if err := os.MkdirAll(filepath.Dir(newFn), os.ModePerm); err != nil {
				errs.Add(errors.Wrapf(err, "create %s", filepath.Dir(newFn)))
				continue
			}
			if err := os.WriteFile(newFn, b, os.ModePerm); err != nil {
				errs.Add(errors.Wrapf(err, "write file %v", newFn))
				continue
			}
			filesByStrategy[s] = append(filesByStrategy[s], newFn)
			ruleFiles[newFn] = fn
		}
	}

View on GitHub (pinned to 35b8b99117)