Skip to content

Recursion prevention not universally reliable #4

@tzinm

Description

@tzinm

Hi! First of all, thanks for sharing this Trigger Framework.

I'm working through the Camp Apex Advent of Apex 2025 (phase 1 focuses on record-triggered automation) and used this framework to implement a simple trigger-based solution. While validating the solution, I noticed unexpected behavior with the framework's recursion prevention.

Context

The first challenge execute automation on before insert trigger event. After implementing the solution, some challenge tests didn't pass. I checked the logs to see how the challenge was running the tests. They execute via Anonymous Apex and perform multiple DML insert operations.

This means the same trigger for the same sObject is fired multiple times in before insert trigger event within the same transaction.

What's happening

The framework’s recursion control is enabled by default (as documented here: Disabling trigger execution. This control blocks the execution for the DML insert operations after the first one.

This is not only reproducible with Anonymous Apex; it can also happen if a one DML operation size exceeds 200 records.

Reproduction scenario

  • Perform a single DML insert with 250 records of the same sObject.
  • Salesforce will split it into two chunks:
    • Chunk 1: 200 records
    • Chunk 2: 50 records
  • Although they are different trigger chunks, they still run in the same transaction.
  • Because recursion control relies on static state across the transaction, the business logic runs for the first chunk but is skipped for the second chunk.

In scenarios where your business logic must run for all records in a single DML operation, the current recursion control prevents correct execution on later chunks. This can lead to partial processing and data inconsistencies.

This pattern appears in other frameworks as well. For example, sfdc-trigger-framework has related issues: "Issue with addToLoopCount method"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions