diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index 52ac4940b77..81ad6fac9d9 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -673,6 +673,28 @@ func TestIntegrationProvisioningApi(t *testing.T) { require.NotEmpty(t, response.Body()) require.Contains(t, string(response.Body()), "invalid alert rule") }) + + t.Run("PUT returns 400 when the alert rule has invalid queries", func(t *testing.T) { + sut := createProvisioningSrvSut(t) + rc := createTestRequestCtx() + group := definitions.AlertRuleGroup{ + Title: "test rule group", + Interval: 60, + Rules: []definitions.ProvisionedAlertRule{ + createTestAlertRule("rule", 1), + }, + } + // Set an invalid query model that will fail PreSave validation + // Invalid JSON should trigger unmarshal error in PreSave + group.Rules[0].Data[0].Model = json.RawMessage(`{invalid json`) + + response := sut.RoutePutAlertRuleGroup(&rc, group, "folder-uid", group.Title) + + require.Equal(t, 400, response.Status()) + require.NotEmpty(t, response.Body()) + require.Contains(t, string(response.Body()), "invalid alert rule") + require.Contains(t, string(response.Body()), "invalid alert query") + }) }) t.Run("have reached the rule quota, PUT returns 403", func(t *testing.T) { diff --git a/pkg/services/ngalert/models/alert_rule.go b/pkg/services/ngalert/models/alert_rule.go index 79c6f7cebd6..d16ace0eb6a 100644 --- a/pkg/services/ngalert/models/alert_rule.go +++ b/pkg/services/ngalert/models/alert_rule.go @@ -642,7 +642,7 @@ func (alertRule *AlertRule) PreSave(timeNow func() time.Time, userUID *UserUID) for i, q := range alertRule.Data { err := q.PreSave() if err != nil { - return fmt.Errorf("invalid alert query %s: %w", q.RefID, err) + return errors.Join(ErrAlertRuleFailedValidation, fmt.Errorf("invalid alert query %s: %w", q.RefID, err)) } alertRule.Data[i] = q }