Skip to content

ACI/workflow-engine: WorkflowEngineRuleSerializer GET response drops fields that PUT accepts, breaking Terraform applies on issue alerts #115160

@InterstellarStella

Description

@InterstellarStella

Summary

After the per-org rollout of the workflow-engine read flags for issue/metric alert endpoints (organizations:workflow-engine-metric-alert-endpoints-get and the related per-method flags from #112827, #111230, #111330), WorkflowEngineRuleSerializer does not round-trip several fields that the corresponding PUT/POST endpoints accept and persist. The values are stored correctly on the server, but the GET response that follows the write does not include them.

For automation that compares the post-apply response to the planned write (notably the jianyuan/terraform-provider-sentry Terraform provider), this surfaces as Provider produced inconsistent result after apply errors and prevents Terraform applies from succeeding, even though the underlying alert configuration on Sentry's side is unchanged.

Affected fields (observed)

For sentry_issue_alert resources (actions_v2, conditions_v2, filters_v2):

  1. actions_v2[*].notify_email.fallthrough_type for target_type = "IssueOwners"

    • PUT body includes fallthroughType: "ActiveMembers" (or "AllMembers" / "NoOne").
    • GET response omits fallthroughType entirely for IssueOwners targets.
    • Code reference: WorkflowEngineRuleSerializer only synthesizes a default fallthroughType for Member/Team targets, see src/sentry/api/serializers/models/rule.py around the # XXX: add default fallthroughType for email Team/Member actions block. There is no equivalent path that re-emits a stored fallthroughType for IssueOwners when the underlying Action.data["fallthrough_type"] is empty.
  2. filters_v2[*].tagged_event.value

    • PUT body includes value: "<some string>".
    • GET response omits value from the serialized tagged_event filter.
    • Code reference: create_tagged_event_data_condition in src/sentry/workflow_engine/migration_helpers/issue_alert_conditions.py only writes value when present in the source blob, and the read-side equivalent does not always re-emit it.
  3. conditions_v2[*].first_seen_event / regression_event / event_frequency / reappeared_event

    • PUT body includes the populated condition object (with name, and for event_frequency the value/interval/comparison_type fields).
    • GET response either drops the entire object or returns it in a different position than it was written, depending on the rule. The provider sees this as was <object>, but now null (or was null, but now <object>).

For sentry_metric_alert resources, separately (this one is arguably "by design" but is the same class of round-trip mismatch):

  1. resolve_threshold is now always returned with the auto-calculated value derived from the lowest-severity trigger's alert_threshold, where the legacy serializer returned null if the user never set it explicitly. This also produces drift in the Terraform provider, though it is not a hard apply failure since PUT-with-null is accepted and re-derived. Code reference: WorkflowEngineDataConditionSerializer.resolve_threshold in src/sentry/incidents/endpoints/serializers/workflow_engine_data_condition.py.

Reproduction

Note: the following is reproducible with any org that has been flipped onto the workflow-engine read path. The provider version below is the one most likely to be in use.

  1. On an organization with the workflow-engine read flags enabled, create an issue alert via the API or UI with the following minimal shape:
{
  "actions": [
    {
      "id": "sentry.mail.actions.NotifyEmailAction",
      "targetType": "IssueOwners",
      "fallthroughType": "ActiveMembers"
    }
  ],
  "conditions": [
    {"id": "sentry.rules.conditions.first_seen_event.FirstSeenEventCondition"}
  ],
  "filters": [
    {
      "id": "sentry.rules.filters.tagged_event.TaggedEventFilter",
      "match": "eq",
      "key": "<some-tag-key>",
      "value": "<some-value>"
    }
  ],
  "actionMatch": "any",
  "filterMatch": "all",
  "frequency": 30,
  "name": "<rule-name>"
}
  1. Immediately GET the same rule via /api/0/projects/<org>/<project>/rules/<id>/ (or the project alert-rule endpoint).

Observed:

  • actions[0].fallthroughType is missing from the response.
  • filters[0].value is missing from the response.
  • The condition object shape may differ from the request.

Expected:

  • The response echoes back the exact fallthroughType, value, and condition object shape that was written, identical to the legacy RuleSerializer behavior for the same rule shape.
  1. Same flow via the jianyuan/terraform-provider-sentry provider (any 0.14.x) using sentry_issue_alert with actions_v2.notify_email, filters_v2.tagged_event, and conditions_v2.{first_seen_event,event_frequency,regression_event,reappeared_event} produces:
Error: Provider produced inconsistent result after apply

When applying changes to sentry_issue_alert.<resource>, provider
"provider[\"registry.terraform.io/jianyuan/sentry\"]" produced an
unexpected new value: .actions_v2[N].notify_email.fallthrough_type: was
cty.StringVal("ActiveMembers"), but now null.

Analogous errors are produced for filters_v2[N].tagged_event.value and conditions_v2[N].*.

Impact

  • Terraform applies against affected orgs fail per-resource and cannot complete cleanly. Customers managing their alerting via Terraform are blocked on any change once their org is flipped onto the workflow-engine read path.
  • Because so many resources are flagged as drifting at once, the cascade of PUT requests increases Slack channel-validation calls and pushes some orgs into Slack-side rate limiting (separate from this issue, but downstream of it).
  • The data on Sentry's side is correct. The regression is purely in the GET response shape.

Suggested direction

The intent of the workflow-engine read serializers is to be a drop-in replacement for the legacy RuleSerializer / AlertRuleSerializer. To honor that, the serializers should round-trip every field the corresponding write endpoints accept, including:

  • Always emit fallthroughType for email actions, with the same defaulting behavior the legacy serializer applies to all targetType values (not just Member/Team).
  • Always emit value on tagged_event filters when the stored data condition has it, and avoid silently dropping it during the legacy-rule-to-data-condition migration.
  • Match the shape and presence of conditions_v2 / filters_v2 / actions_v2 sub-objects exactly, including the name fields, so that providers comparing pre/post can converge.

If a fully drop-in fix isn't feasible quickly, please consider rolling the per-method workflow-engine read flags back for affected orgs while patching, since the impact is a hard block on Terraform-managed alerting.

Versions

  • Sentry SaaS, US region.
  • jianyuan/sentry Terraform provider 0.14.13 (also reproduced on earlier 0.14.x).
  • Issue first observed when the org's workflow-engine read flag flipped on.

Related

Metadata

Metadata

No fields configured for issues without a type.

Projects

Status

Waiting for: Product Owner

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions