Share via

ADF Storage Event Trigger StartAsync() Fails Due to Event Grid Provisioning Lock in .NET SDK

Rifatul Islam 0 Reputation points
2026-03-24T14:44:32.81+00:00

When starting an Azure Data Factory Storage Event Trigger using the .NET SDK, the StartAsync() call may fail with “Resource cannot be updated during provisioning” even after waiting or retrying.

This happens because the trigger depends on an underlying Event Grid subscription. While the Azure Portal shows “Event Subscriptions are updating,” the resource remains locked internally.

The SDK method StartAsync() only waits for ARM-level completion and does not account for backend Event Grid provisioning and also there is no exposed property to check this state

Azure Event Grid
Azure Event Grid

An Azure event routing service designed for high availability, consistent performance, and dynamic scale.


2 answers

Sort by: Most helpful
  1. Praveen Kumar Gudipudi 2,275 Reputation points Microsoft External Staff Moderator
    2026-03-24T17:00:16.9266667+00:00

    Hello Rifatul Islam,

    Thank you for reaching out regarding the issue with starting the Storage Event Trigger using the .NET SDK.

    Summary of the Issue

    We understand that when invoking StartAsync() on an Azure Data Factory Storage Event Trigger, the operation intermittently fails with the error:

    "Resource cannot be updated during provisioning"

    even after incorporating delays or retries.

    This behavior is related to the underlying dependency between Azure Data Factory Storage Event Triggers and Azure Event Grid subscriptions.

    When a Storage Event Trigger is created or updated:

    An associated Event Grid subscription is provisioned asynchronously in the backend.

    While the Azure Resource Manager (ARM) operation may complete successfully, the Event Grid subscription can still be in a provisioning state.

    During this time, the resource is internally locked, and any subsequent operations such as StartAsync() may fail with:

    "Resource cannot be updated during provisioning"

    At present, the .NET SDK StartAsync() method only tracks ARM-level completion and does not account for the backend provisioning status of the Event Grid subscription. Additionally, there is no exposed SDK property to validate this provisioning state.

    Recommended Approach:

    To mitigate this issue, we recommend the following:

    Implement Retry Logic with Exponential Backoff

    Handle the specific provisioning error and retry the StartAsync() operation after a delay (for example, 15–30 seconds, increasing gradually).

    Introduce a Stabilization Delay

    After creating or updating the trigger, allow a buffer time (typically 1–2 minutes) before invoking StartAsync().

    Ensure Idempotent Operations

    Design your implementation so repeated StartAsync() calls do not cause unintended side effects.

    Portal Validation (Optional for Testing)

    In the Azure Portal, verify whether the Event Subscription shows a status such as “Updating”. Once this completes, the trigger start operation should succeed.

    Additional Notes

    This is a known behavior due to eventual consistency between ARM and downstream resource providers. While this may appear intermittent, it is dependent on backend provisioning timelines within Event Grid.

    Conclusion

    The observed failure is not indicative of an issue with your implementation, but rather a timing dependency on Event Grid provisioning. Incorporating retry logic and a short delay before starting the trigger should help ensure consistent success.

    This is not a bug in your implementation, but a timing gap between ARM and Event Grid provisioning. Since the SDK does not expose Event Grid readiness, the most reliable approach is retry with backoff + slight delay before starting the trigger.

    Please accept as answer and do a Thumbs-up to upvote this response if you are satisfied with the community help. Your upvote will be beneficial for the community users facing similar issues.


  2. Q&A Assist
    2026-03-24T14:44:54.5466667+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    The described behavior is expected because starting a Data Factory storage event trigger involves two distinct layers of operations:

    1. An ARM/ADF trigger start operation.
    2. Backend Event Grid event subscription provisioning.

    DataFactoryTriggerResource.StartAsync(WaitUntil, CancellationToken) only tracks the long‑running ARM operation for the trigger start (Triggers_Start), not the internal Event Grid subscription provisioning state. ARM can report completion while Event Grid is still provisioning or updating the underlying event subscription, which can leave the trigger in a transient “locked” state where updates fail with messages like “Resource cannot be updated during provisioning.”

    Event Grid itself exposes a provisioningState for create/update/delete operations, where only Succeeded, Failed, or Canceled indicate completion; any other value (for example, Accepted) means the operation is still running and the resource may be locked for updates.

    For Data Factory triggers, the SDK surface that exposes the event subscription status is separate from StartAsync:

    • In the newer Azure.ResourceManager.DataFactory SDK:
      • DataFactoryTriggerResource.GetEventSubscriptionStatusAsync() returns a DataFactoryTriggerSubscriptionOperationResult that represents the trigger’s event subscription status.
    • In the older Microsoft.Azure.Management.DataFactory SDK:
      • BeginSubscribeToEventsAsync(...) starts subscription to events and returns a TriggerSubscriptionOperationStatus.
      • GetEventSubscriptionStatusWithHttpMessagesAsync(...) returns TriggerSubscriptionOperationStatus wrapped in AzureOperationResponse, which can be used to inspect the subscription status.

    Because StartAsync does not wait on Event Grid provisioning, robust code should:

    1. Call StartAsync(WaitUntil.Started or Completed) to initiate the trigger start.
    2. Poll the trigger’s event subscription status until it indicates completion, using:
      • GetEventSubscriptionStatusAsync() in the Azure.ResourceManager.DataFactory library, or
      • GetEventSubscriptionStatusWithHttpMessagesAsync() (or the corresponding convenience method) in Microsoft.Azure.Management.DataFactory.
    3. Only treat the trigger as fully started once the event subscription status indicates that the subscription operation has completed successfully.
    4. If the status indicates the subscription is still being created/updated, implement retry logic with backoff before attempting further StartAsync or other update operations.

    This pattern aligns with Event Grid’s general guidance: operations that are still provisioning return a provisioningState other than Succeeded/Failed/Canceled, and update operations can be blocked while that state is in progress. Retrying StartAsync alone without checking the subscription status can work eventually, but polling the event subscription status provides a more deterministic and observable approach.

    Additionally, ensure the storage event trigger prerequisites are satisfied so that Event Grid subscription creation can succeed and not remain stuck:

    • The subscription must be registered with the Microsoft.EventGrid resource provider, and the caller must have Microsoft.EventGrid/eventSubscriptions/* permissions (for example, via the EventGrid EventSubscription Contributor role).
    • If the storage account is behind a private endpoint or has network restrictions, configure network rules or Event Grid private endpoints so Event Grid can communicate with the storage account.
    • Be aware that storage event triggers rely on Event Grid and are subject to its limits and behaviors (for example, max 500 storage event triggers per storage account).

    In summary, the correct mitigation is to combine StartAsync with explicit polling of the trigger’s event subscription status and to implement retry logic until the Event Grid provisioning has completed, rather than relying on StartAsync alone to represent end‑to‑end readiness.


    References:

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.