Skip to content Skip to sidebar

This thread is resolved. Here is a description of the problem and solution.

Problem:

If you're experiencing a fatal error with a message about 'Maximum call stack size' and suspect it might be due to infinite recursion in the WPML plugin, particularly when using Advanced Custom Fields (ACF).

Solution:

We recommend checking if your issue matches the one described in our errata page for Advanced Custom Fields - Fatal error on secondary-language options pages with taxonomy fields. You can find the errata here: Advanced Custom Fields - Fatal error on secondary-language options pages with taxonomy fields.

If the errata matches your issue, please apply the patch provided

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

Tagged: 

This topic contains 2 replies, has 0 voices.

Last updated by Pierre Sylvestre 2 days, 2 hours ago.

Assisted by: Pierre Sylvestre.

Author Posts
March 13, 2026 at 2:19 pm #17895847

petrH-5

Affected versions:
- WPML Multilingual CMS: 4.9.2
- ACFML (Advanced Custom Fields Multilingual): 2.2.1
- ACF Pro: 6.x
- PHP: 8.3.30

Steps to reproduce:
1. Create an ACF Options Page with 50+ fields, including post_object and taxonomy field types
2. Set WPML translation preferences on these fields to "Copy" or "Copy once"
3. Navigate to the Options Page in a non-default language (e.g. ?page=website-settings&lang=en)

Expected: Options page loads normally.

Actual: Fatal error:
Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?

Root cause analysis:

There are two compounding issues in ACFML\Options\EditorHooks::preRenderOnTranslatedOptionsPage():

Issue 1 — Excessive stack depth per field:

The acf/load_value closure added at line 103 calls $this->sitepress->get_current_language() (line 117) for every single field. Each call passes
through WPML_Language_Resolution::filter_for_legal_langs() which calls Str::includes() — this goes through the WPML FP currying/pipe/compose
chain consuming ~24 stack frames per invocation. With 90+ fields this adds up significantly but alone doesn't cause overflow.

Issue 2 — True recursion via convertRelationshipField (the actual crash):

For fields with WPML_COPY_CUSTOM_FIELD or WPML_COPY_ONCE_CUSTOM_FIELD preferences, the closure calls convertRelationshipField() which triggers:

EditorHooks closure (acf/load_value filter)
→ convertRelationshipField()
→ WPML_ACF_Worker::convertMetaValue()
→ WPML_ACF_Field::convert_ids()
→ WPML_ACF_Term_Id::convert()
→ get_field_object() ← triggers ACF field loading
→ acf_get_value()
→ apply_filters('acf/load_value')
→ EditorHooks closure ← re-enters the same filter
→ convertRelationshipField()
→ ... (infinite loop)

WPML_ACF_Term_Id::convert() at line 45 calls get_field_object(), which internally calls acf_get_value(), which fires the acf/load_value filter
— re-entering the same ACFML closure. This creates genuine infinite recursion.

Why this only manifests on PHP 8.3+:

PHP 8.3 introduced zend.max_allowed_stack_size which actively detects deep/infinite recursion. On PHP 8.2 and below, the same recursion occurs
but is not detected — the process either survives (if OS stack limit is large enough) or segfaults silently.

Why this only manifests with many fields:

Small Options Pages with few relationship-type fields may not trigger convertRelationshipField or may not nest deeply enough to exceed the
stack limit. The threshold depends on the number of post_object/taxonomy fields with Copy/Copy-once translation preferences.

Suggested fix:

1. Add a re-entrancy guard to the acf/load_value closure in preRenderOnTranslatedOptionsPage() to prevent recursive field loading:

add_filter( 'acf/load_value', function( $value, $fieldPostId, $field ) use ( $postId ) {
static $processing = false;
if ( $processing ) {
return $value; // prevent re-entrant calls from convertRelationshipField
}
// ... existing checks ...
$processing = true;
$currentLanguage = $this->sitepress->get_current_language();
// ... existing logic ...
$processing = false;
return $result;
}, 10, 3 );

2. Cache get_current_language() result in a variable before the closure, rather than calling it per-field inside acf/load_value. This
eliminates ~24 unnecessary FP stack frames per field.

Our current workaround (in theme's functions.php):

We unhook preRenderOnTranslatedOptionsPage from acf/pre_render_fields and replace it with a patched version that (a) caches
get_current_language() and (b) includes a static $processing re-entrancy guard. This fully resolves the crash.

March 13, 2026 at 2:27 pm #17895893

Pierre Sylvestre
Supporter

Languages: English (English ) French (Français ) Portuguese (Brazil) (Português )

Timezone: America/Sao_Paulo (GMT-03:00)

Hi @petrH-5,

Your issue could be the same as Advanced Custom Fields - Fatal error on secondary-language options pages with taxonomy fields. Could you please check this errata, and if it matches, apply and confirm the patch?

Thanks,
Pierre

March 13, 2026 at 2:37 pm #17895961

petrH-5

Hi, thank you for the suggested fix, I can confirm it resolves the issue completely.

Could you let me know when the next ACFML release containing this fix is expected? I'd like to track this so I can remove the manual patch once the official update is available.

Thanks for the quick support.

March 13, 2026 at 2:40 pm #17895974

Pierre Sylvestre
Supporter

Languages: English (English ) French (Français ) Portuguese (Brazil) (Português )

Timezone: America/Sao_Paulo (GMT-03:00)

Thanks for the confirmation @petrH-5!

We should release an ACFML hot-fix version early next week (possibly on Monday).

Concerning, the optimization with `get_current_language`, I will escalate to our WPML Core project.