Skip to content

Infinite recursion in content.html.twig when a custom page extends it without overriding content_title/page_title #7633

@aphex008

Description

@aphex008

Description

@EasyAdmin/page/content.html.twig defines two blocks that reference each other with no base case:

{# deprecated 'The "page_title" block is deprecated, use "content_title" instead.' #}
{% block page_title %}{{ block('content_title') }}{% endblock %}

{% block content_title %}{{ block('page_title') }}{% endblock %}

page_titlecontent_titlepage_title → … This is fine for EasyAdmin's own CRUD pages because they always override content_title. But any custom page (e.g. a Dashboard homepage) that extends @EasyAdmin/page/content.html.twig and overrides neither block recurses infinitely the moment the title is rendered — layout.html.twig evaluates page_title to build the <title>:

{% set page_title_block_output %}{% block page_title %}{{ block('content_title') }}{% endblock %}{% endset %}
<title>{{ page_title_block_output|striptags|raw }}</title>

How to reproduce

DashboardController:

#[Route('/admin', name: 'admin')]
public function index(): Response
{
    return $this->render('admin/dashboard.html.twig');
}

templates/admin/dashboard.html.twig (overrides neither title block):

{% extends '@EasyAdmin/page/content.html.twig' %}

Open /admin.

Expected

The dashboard renders (empty content is fine).

Actual

Infinite recursion. The exact symptom depends on which PHP limit trips first:

  • dev (Symfony profiler on): the Twig profiler instruments every recursion level (microtime()/memory_get_usage()/new Twig\Profiler\Profile), slowing it down so it hits max_execution_time first:
    Fatal error: Maximum execution time of N seconds exceeded
    at vendor/twig/twig/src/Extension/ProfilerExtension.php:32
    
    (misleadingly points at the profiler, which is just the innermost frame)
  • prod / profiler off: native stack overflow:
    Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?
    

Confirmed by Xdebug profiling: @EasyAdmin/page/content.html.twig is re-entered ~110k times/9s at flat-ish depth — the mutual block() calls.

Root cause

The page_titlecontent_title blocks are mutually recursive with no terminating output. Since both are deprecated and kept only for BC, neither provides a real default, so nothing breaks the cycle unless the leaf template overrides one.

Workaround

Override content_title (or page_title) in the custom template:

{% extends '@EasyAdmin/page/content.html.twig' %}
{% block content_title %}Dashboard{% endblock %}
{% block main %}{% endblock %}

Versions

  • easycorp/easyadmin-bundle: 4.29.11 (blocks still mutually-referencing on 4.x)
  • twig/twig: 3.27.1
  • symfony: 5.4
  • PHP: 8.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions