A synchronous PostOperation plug-in on Update of the opportunity table updates the same opportunity to set a calculated score. Saving any opportunity now runs repeatedly until Dataverse stops it with an infinite loop error. What is the appropriate guard in the plug-in?
Select an answer to reveal the explanation.
Short Explanation
Depth is the plug-in's way of telling you how deep down the rabbit hole you are. If it's greater than 1, your own update probably triggered you, so bail out. Static flags look clever, but they're shared across threads and will burn you in production.
Full Explanation
Each time a plug-in triggers another operation, Dataverse increments the Depth value in the execution context of the resulting pipeline. A plug-in that updates the row it was triggered by causes another Update event, which runs the same step again, and Dataverse eventually stops the chain when depth exceeds its limit within a time window. Checking context.Depth at the start of Execute and returning when it is greater than 1 stops the recursive call from repeating the logic. Pairing the check with filtering attributes, so the step fires only when the inputs to the score change, further reduces unnecessary executions. Catching the exception does not prevent recursion; the loop error surfaces only after many nested executions, and the transaction is still rolled back. Static fields on plug-in classes are shared across concurrent executions because Dataverse caches plug-in instances, so a static flag causes race conditions and data leaks between requests. Moving to PreValidation does not stop events from triggering other steps; an Update issued from any stage starts a new pipeline. Exam caveat: Depth is also greater than 1 when a legitimate parent operation triggers the plug-in, so the threshold must reflect the expected call chain. Operational check: add the Depth guard and filtering attributes, update one opportunity, and confirm one recalculation in the trace log.