EasyCorp / EasyCorp/EasyAdminBundle
Infinite recursion in content.html.twig when a custom page extends it without overriding content_title/page_title
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 4.3k
- Forks
- 1.1k
- Avg merge
- 8d 2h
- Merged PRs (30d)
- 11
Description
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_title → content_title → page_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 hitsmax_execution_timefirst:
(misleadingly points at the profiler, which is just the innermost frame)Fatal error: Maximum execution time of N seconds exceeded at vendor/twig/twig/src/Extension/ProfilerExtension.php:32 - 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_title ↔ content_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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with @EasyAdmin/page/content.html.twig and the page_title evaluation in layout.html.twig, then reproduce the issue with a custom dashboard template that overrides neither title block. Confirm the change stops recursion while preserving the documented title-block workaround and lets the dashboard render with empty content.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php, symfony
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100