thanos-io/thanos · error
rule: recording rule unmarshal
Error message
rule: recording rule unmarshal: %v
What it means
When Rule.UnmarshalJSON sees type == "recording", it unmarshals the same entry into a RecordingRule; failure is wrapped as 'rule: recording rule unmarshal' with the raw entry. The type field was valid but the recording-rule payload is missing or mistyping required fields (e.g. record/expr not strings).
Solutions
- Compare the entry against the RecordingRule schema (record, expr string fields) and fix types/values
- Regenerate the rules file from a validated Prometheus rules format
- Check for version skew between the producer of the JSON and the current rulespb schema
Example fix
// before
{"type": "recording", "record": 123, "expr": "sum(rate(x[5m]))"}
// after
{"type": "recording", "record": "job:rate5m", "expr": "sum(rate(x[5m]))"} Defensive patterns
Strategy: validation
Validate before calling
var probe struct {
Type string `json:"type"`
Record string `json:"record"`
Expr string `json:"expr"`
}
if err := json.Unmarshal(entry, &probe); err != nil || probe.Record == "" || probe.Expr == "" {
return fmt.Errorf("not a valid recording rule")
} Try / catch
if err := json.Unmarshal(entry, &rule); err != nil {
if strings.Contains(err.Error(), "recording rule unmarshal") {
log.Printf("bad recording rule entry: %s", entry)
}
return err
} Prevention
- Keep record and expr as strings in rule JSON
- Validate rules against the rulespb schema in CI
- Convert Prometheus YAML rules with a maintained converter
When it happens
Trigger: A rule entry with "type": "recording" whose fields don't match the RecordingRule JSON schema — wrong types (record as number), unknown incompatible shape, or JSON valid for one schema version but not another.
Common situations: YAML/JSON rules converted between Prometheus and Cortex formats; schema changes after upgrading rulespb; hand-edited rules with wrong field types.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- unmarshal marker JSON
- unmarshal response
- unmarshal query instant response
- unmarshal query range response
- decode result into ValueTypeMatrix
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/902899185ae06d7a.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/rules/rulespb/custom.go:220
return ""
}
return r.File + ";" + r.Name
}
func (m *Rule) UnmarshalJSON(entry []byte) error {
decider := struct {
Type string `json:"type"`
}{}
if err := json.Unmarshal(entry, &decider); err != nil {
return errors.Wrapf(err, "rule: type field unmarshal: %v", string(entry))
}
switch strings.ToLower(decider.Type) {
case "recording":
r := &RecordingRule{}
if err := json.Unmarshal(entry, r); err != nil {
return errors.Wrapf(err, "rule: recording rule unmarshal: %v", string(entry))
}
m.Result = &Rule_Recording{Recording: r}
case "alerting":
r := &Alert{}
if err := json.Unmarshal(entry, r); err != nil {
return errors.Wrapf(err, "rule: alerting rule unmarshal: %v", string(entry))
}
m.Result = &Rule_Alert{Alert: r}
case "":
return errors.Errorf("rule: no type field provided: %v", string(entry))
default:
return errors.Errorf("rule: unknown type field provided %s; %v", decider.Type, string(entry))
}
return nil
}
View on GitHub (pinned to 35b8b99117)