Skip to content

Dynamic Content ACF repeater traversal exceeds execution time on cyclic parent chain #2976

Description

@pirate-bot

Summary

Rendering Dynamic Content for an ACF repeater sub-field can terminate the frontend request after PHP reaches its execution-time limit.

Expected behavior: Dynamic Content either resolves the requested repeater sub-field or safely stops when its field hierarchy cannot be traversed.

Actual behavior: The request can run until the configured PHP timeout and produce Maximum execution time of 900 seconds exceeded.

Impact: Affected pages fail to render while the Dynamic Content ACF lookup is evaluated.

Customer context

  • Product / area: Otter Pro Dynamic Content, ACF repeater sub-fields
  • Version: 3.2.2
  • Environment: Frontend requests on WordPress 7.0.4 with PHP 8.1.34 and PHP 8.4.22
  • Integration / third party: Advanced Custom Fields
  • Reported error / symptom: Maximum execution time of 900 seconds exceeded
  • Impact: 19 production fatal occurrences across 3 distinct sites between 2026-08-13 and 2026-08-15.

Reproduction notes

  1. Configure an Otter Pro Dynamic Content value that resolves an ACF repeater sub-field whose direct ACF value is empty.
  2. Provide an ACF field-parent lookup sequence that repeats a previously returned field instead of reaching a missing parent.
  3. Render the affected content on the frontend.

Reproduction is code-confirmed from the non-terminating traversal; the telemetry does not include the exact ACF configuration needed to recreate the production hierarchy.

Diagnosis

Conclusion

The production location maps exactly to Dynamic_Content::get_acf_repeater_sub_field() at the cursor reassignment inside its while ( true ) parent walk. That loop stops only when acf_get_field() returns no parent and has no repeated-parent or maximum-depth guard. A cyclic ACF field-parent result therefore does not terminate, matching the timeout fatal recorded at line 314.

Where this likely occurs

  • plugins/otter-pro/inc/plugins/class-dynamic-content.phpDynamic_Content::evaluate_content() lines 45-64 routes ACF Dynamic Content through get_acf() for frontend rendering when the Pro license hooks are active.
  • plugins/otter-pro/inc/plugins/class-dynamic-content.phpDynamic_Content::get_acf() lines 240-257 invokes get_acf_repeater_sub_field() when the selected ACF value is empty.
  • plugins/otter-pro/inc/plugins/class-dynamic-content.phpDynamic_Content::get_acf_repeater_sub_field() lines 299-315 uses an unconditional ancestor loop; telemetry's line 314 is $cursor = $parent in the v3.2.2 source.
  • The loop was introduced by commit 1e72ae1c5f8cbdaf5e3aa33b6d0ba969c2b26969 (feat: add ACF repeater field support) and is present in tags v3.2.0, v3.2.1, and v3.2.2.

Engineering notes

The affected code is in the Pro package within the Codeinwp/otter-blocks monorepo, not the Themeisle SDK. The execution path requires an active Pro Dynamic Content integration, ACF availability, a requested ACF field whose direct value is empty, and an ancestor chain returned by ACF that does not reach a missing parent. The telemetry does not expose the ACF field definitions, so the malformed or cyclic hierarchy is inferred from the code path and timeout location rather than directly observed.

A matching unconditional parent walk also exists in Dynamic_Content::get_acf_repeater_sub_field_image() at plugins/otter-pro/inc/plugins/class-dynamic-content.php lines 389-410. That surface was not named by the fatal location and remains a related compatibility case rather than confirmed impact.

Test coverage status

tests/test-dynamic-content.php lines 891-1011 covers collection of already-resolved nested repeater rows, empty collection paths, and image-value collection. No relevant coverage was found during inspection for get_acf_repeater_sub_field() ancestor traversal, cyclic parent references, or repeated ACF parents.

What to verify or explore next

  • May be worth reproducing with an ACF field lookup that returns a parent cycle while rendering an ACF Dynamic Content value on the frontend.
  • May be worth checking the equivalent image repeater lookup with the same parent sequence.
  • If reproducible, run the Dynamic Content PHPUnit suite containing tests/test-dynamic-content.php against the supported ACF and WordPress combinations.

Unknowns / follow-up

  • The affected sites' ACF versions and exact field-parent data were not included in the telemetry.
  • It is unknown whether the cyclic response originates from stored ACF configuration, an ACF compatibility change, or another plugin altering acf_get_field() results.

Confidence

Confidence: 94/100

Production telemetry records 19 frontend fatals on three sites using Otter Pro 3.2.2, and the reported line resolves exactly to an unbounded ACF ancestor traversal in the Pro Dynamic Content code. The loop has no repeated-parent or depth termination condition.

Crash telemetry

Occurrences 19
Distinct sites 3
First seen 2026-08-13 17:46 UTC
Last seen 2026-08-15 02:08 UTC
Crash location product:inc/plugins/class-dynamic-content.php:314
Request context frontend
Inside Themeisle SDK no
Product versions 3.2.2
WP versions 7.0.4
PHP versions 8.1.34, 8.4.22
SDK versions 3.3.58

Source: automated crash report — otter-pro, fingerprint 2417ff35ad27ff88fb1d4002af4dba15
Generated by bug-report-triage (ID: bug-report-triage_6a80008f3443b0.07314561)

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions