{"record":{"id":"231432366b5b1b7b","repo":"thanos-io/thanos","slug":"rule-q-unsupported-type-t","errorCode":null,"errorMessage":"rule %q: unsupported type %T","messagePattern":"rule %q: unsupported type %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/rules/manager.go","lineNumber":91,"sourceCode":"\t\t\t\t\tEvaluationDurationSeconds: rule.GetEvaluationDuration().Seconds(),\n\t\t\t\t\t// UTC needed due to https://github.com/gogo/protobuf/issues/519.\n\t\t\t\t\tLastEvaluation: rule.GetEvaluationTimestamp().UTC(),\n\t\t\t\t}}})\n\t\tcase *rules.RecordingRule:\n\t\t\tret.Rules = append(ret.Rules, &rulespb.Rule{\n\t\t\t\tResult: &rulespb.Rule_Recording{Recording: &rulespb.RecordingRule{\n\t\t\t\t\tName:                      rule.Name(),\n\t\t\t\t\tQuery:                     rule.Query().String(),\n\t\t\t\t\tLabels:                    labelpb.ZLabelSet{Labels: labelpb.ZLabelsFromPromLabels(rule.Labels())},\n\t\t\t\t\tHealth:                    string(rule.Health()),\n\t\t\t\t\tLastError:                 lastError,\n\t\t\t\t\tEvaluationDurationSeconds: rule.GetEvaluationDuration().Seconds(),\n\t\t\t\t\t// UTC needed due to https://github.com/gogo/protobuf/issues/519.\n\t\t\t\t\tLastEvaluation: rule.GetEvaluationTimestamp().UTC(),\n\t\t\t\t}}})\n\t\tdefault:\n\t\t\t// We cannot do much, let's panic, API will recover.\n\t\t\tpanic(fmt.Sprintf(\"rule %q: unsupported type %T\", r.Name(), rule))\n\t\t}\n\t}\n\treturn ret\n}\n\nfunc ActiveAlertsToProto(s storepb.PartialResponseStrategy, a *rules.AlertingRule) []*rulespb.AlertInstance {\n\tactive := a.ActiveAlerts()\n\tret := make([]*rulespb.AlertInstance, len(active))\n\tfor i, ruleAlert := range active {\n\t\t// UTC needed due to https://github.com/gogo/protobuf/issues/519.\n\t\tactiveAt := ruleAlert.ActiveAt.UTC()\n\t\tret[i] = &rulespb.AlertInstance{\n\t\t\tPartialResponseStrategy: s,\n\t\t\tLabels:                  labelpb.ZLabelSet{Labels: labelpb.ZLabelsFromPromLabels(ruleAlert.Labels)},\n\t\t\tAnnotations:             labelpb.ZLabelSet{Labels: labelpb.ZLabelsFromPromLabels(ruleAlert.Annotations)},\n\t\t\tState:                   rulespb.AlertState(ruleAlert.State),\n\t\t\tActiveAt:                &activeAt,\n\t\t\tValue:                   strconv.FormatFloat(ruleAlert.Value, 'e', -1, 64),","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/rules/manager.go#L73-L109","documentation":"toProto converts a rule to protobuf; when the rule's concrete type matches none of the supported cases (AlertingRule, RecordingRule), it panics deliberately. The HTTP API recovers the panic, so it surfaces as a recovered internal error, not a normal error return.","triggerScenarios":"A rules.Group or RulesStore contains a rules.Rule implementation that is neither *rules.AlertingRule nor *rules.RecordingRule — typically a new rule type added in Prometheus/Thanos without updating toProto, or a mock rule leaking into production paths.","commonSituations":"Version mismatch between the Prometheus rules library and Thanos; custom/test rule implementations; upstream Prometheus added a new rule kind.","solutions":["Upgrade Thanos to a version supporting the rule type (or align Prometheus dependency versions)","Identify the unexpected %T printed in the panic message and check which code created it","If you embed the rules manager, ensure only AlertingRule/RecordingRule enter groups","Recover at API boundary — this is already done via panic+recover by design"],"exampleFix":"// before\ncase *rules.AlertingRule: ...; default: panic(...)\n// after\ncase *rules.RecordingRule: ...\ncase *rules.AlertingRule: ...\ndefault:\n    level.Error(logger).Log(\"msg\", \"unsupported rule type\", \"type\", fmt.Sprintf(\"%T\", rule))","handlingStrategy":"type-guard","validationCode":"switch rule.(type) {\ncase *rules.AlertingRule, *rules.RecordingRule:\n    // safe to convert\ndefault:\n    return fmt.Errorf(\"rule %q: unsupported type %T\", rule.Name(), rule)\n}","typeGuard":"func isConvertibleRule(r rules.Rule) bool {\n    switch r.(type) {\n    case *rules.AlertingRule, *rules.RecordingRule:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"func safeToProto(...) (ret []*rulespb.Rule, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"toProto panicked: %v\", r)\n        }\n    }()\n    ret = toProto(...)\n    return\n}","preventionTips":["Keep the Prometheus rules library version aligned with Thanos's supported types","Never inject custom or mock rule implementations into production managers","Cover both rule kinds in conversion unit tests"],"tags":["panic","protobuf","rules"],"backgroundTag":"internal-invariant-violation","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}