Skip to content

fix(api): surface subscription deletion errors to users#24

Open
tomerqodo wants to merge 12 commits intosentry_only-issues-20260113-augment-codex-sentry_base_fixapi_surface_subscription_deletion_errors_to_users_pr181from
sentry_only-issues-20260113-augment-codex-sentry_head_fixapi_surface_subscription_deletion_errors_to_users_pr181
Open

fix(api): surface subscription deletion errors to users#24
tomerqodo wants to merge 12 commits intosentry_only-issues-20260113-augment-codex-sentry_base_fixapi_surface_subscription_deletion_errors_to_users_pr181from
sentry_only-issues-20260113-augment-codex-sentry_head_fixapi_surface_subscription_deletion_errors_to_users_pr181

Conversation

@tomerqodo
Copy link

Benchmark PR from qodo-benchmark#181

Mairuis and others added 12 commits December 29, 2025 18:01
Previously, when rebuilding a trigger subscription, errors from the
unsubscribe operation were silently caught and logged without
propagating to the user. This left users unaware of failures during
subscription management.

Changes:
- Check UnsubscribeResult.success and raise ValueError with the error
  message when unsubscribe fails
- Simplify the rebuild logic by removing unnecessary try/except wrapper
- Refactor update API to use cleaner conditional logic
- Remove redundant test cases that tested silent error handling
… TriggerSubscriptionUpdateRequest

- Introduced a model validator in TriggerSubscriptionUpdateRequest to enforce that at least one of the fields (name, credentials, parameters, properties) must be provided.
- Refactored the TriggerSubscriptionUpdateApi to use the validated request object and simplified the logic for updating subscriptions based on the credential type.
- Updated the credential type check in TriggerProviderService to use a set for better performance and clarity.
…oviderService

- Deleted the test for rebuilding trigger subscriptions with unsupported credential types, as it was deemed unnecessary.
- This change helps streamline the test suite by focusing on relevant scenarios.
Comment on lines +871 to +878
subscription = TriggerProviderService.get_subscription_by_id(
tenant_id=tenant_id,
subscription_id=subscription_id,
)
if not subscription:
raise ValueError(f"Subscription {subscription_id} not found")

# Commit the transaction
session.commit()
credential_type = CredentialType.of(subscription.credential_type)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The rebuild_trigger_subscription method incorrectly passes the literal HIDDEN_VALUE string to external APIs during partial credential updates, instead of merging with the existing stored credential.
Severity: CRITICAL

Suggested Fix

Reinstate the logic to merge credentials in rebuild_trigger_subscription. Before calling TriggerManager.subscribe_trigger, iterate through the incoming credentials dictionary. If a value is HIDDEN_VALUE, replace it with the corresponding value from the original, decrypted subscription.credentials.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: api/services/trigger/trigger_provider_service.py#L871-L878

Potential issue: The `rebuild_trigger_subscription` service method no longer merges
existing credentials when a request contains `HIDDEN_VALUE` placeholders for fields that
are not being changed. Instead, it passes the credentials object, including the literal
`HIDDEN_VALUE` string, directly to the `TriggerManager`. This will cause subscription
rebuilds to fail when a user performs a partial credential update, as the external
provider will receive an invalid credential value.

Did we get this right? 👍 / 👎 to inform future reviews.

user_id=user_id,
provider_id=provider_id,
subscription=subscription.to_entity(),
credentials=subscription.credentials,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The rebuild_trigger_subscription method is missing error handling for the unsubscribe_trigger call. A failure in this external API call will now crash the entire operation.
Severity: HIGH

Suggested Fix

Wrap the TriggerManager.unsubscribe_trigger call within a try...except Exception block, similar to the implementation in delete_trigger_provider. Log the exception for debugging purposes but do not re-raise it, allowing the rebuild process to continue to the subscription step.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: api/services/trigger/trigger_provider_service.py#L889

Potential issue: The `rebuild_trigger_subscription` method no longer gracefully handles
exceptions from the `TriggerManager.unsubscribe_trigger` call. Previously, this
operation was wrapped in a `try...except` block to allow the process to continue even if
the unsubscribe call failed. Now, any failure in the external API call will raise an
unhandled exception, halting the entire rebuild process and leaving the subscription in
an inconsistent state. This behavior is inconsistent with other methods like
`delete_trigger_provider` which still handle this error gracefully.

Did we get this right? 👍 / 👎 to inform future reviews.

Comment on lines +368 to +378
# For the rest cases(API_KEY, OAUTH2)
# we need to call third party provider(e.g. GitHub) to rebuild the subscription
TriggerProviderService.rebuild_trigger_subscription(
tenant_id=user.current_tenant_id,
name=request.name,
provider_id=provider_id,
subscription_id=subscription_id,
credentials=request.credentials or subscription.credentials,
parameters=request.parameters or subscription.parameters,
)
return 200
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Updating properties on a manually created (UNAUTHORIZED) subscription without also changing its name incorrectly calls rebuild_trigger_subscription, causing a ValueError due to an unsupported credential type.
Severity: HIGH

Suggested Fix

Modify the conditional logic in the controller. Before falling through to rebuild_trigger_subscription, add a check for CredentialType.UNAUTHORIZED. If the subscription is of this type, route the request to update_trigger_subscription to handle name and property updates, preventing the call to the incompatible rebuild service.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: api/controllers/console/workspace/trigger_providers.py#L368-L378

Potential issue: When updating a manually created subscription (type `UNAUTHORIZED`), if
the update request modifies properties but does not change the name, the request is
incorrectly routed to the `rebuild_trigger_subscription` service. This service contains
a validation check that explicitly rejects `UNAUTHORIZED` credential types, causing a
`ValueError`. The correct behavior would be to route such updates to
`update_trigger_subscription`, which can handle property-only changes for these
subscription types.

Did we get this right? 👍 / 👎 to inform future reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants