EasyAdminBundle: Template twig error in production mode
Describe the bug I have a Symfony project where I use EasyAdmin based on docker compose. The error occurs only in the dashboard, and only in production mode. I tried testing in a clean install with no extra dependencies and configuration to make sure it wasn’t my settings that were causing the problem. However, the error still doesn’t go anywhere, could you also check and maybe find the problem.
To Reproduce
- Clone the setup repository.
- Run in developer mode:
docker compose build --no-cacheanddocker compose up --pull -d --wait - In php containers, install the following composer dependencies:
easycorp/easyadmin-bundleandsymfony/orm-pack - Add a Dashboard controller, as well as any CRUD controller (if not already there), for example for the User entity
- Restart docker compose in production mode:
docker compose down --remove-orphans,CADDY_MERCURE_JWT_SECRET=secret docker compose -f compose.yaml -f compose.prod.yaml build --no-cache, andCADDY_MERCURE_JWT_SECRET=secret docker compose -f compose.yaml -f compose.prod.yaml up --pull -d --wait - Go to the
/adminpage, and go through the CRUD pages several times, if necessary, perform actions to trigger an error.
(OPTIONAL) Additional context
This is the error in the logs:
{ "message": "Uncaught PHP Exception TypeError: \"Twig\\Environment::getTemplateClass(): Argument #1 ($name) must be of type string, null given, called in /app/vendor/twig/twig/src/Template.php on line 319\" at /app/vendor/twig/twig/src/Environment.php line 262", "context": { "exception": { "class": "TypeError", "message": "Twig\\Environment::getTemplateClass(): Argument #1 ($name) must be of type string, null given, called in /app/vendor/twig/twig/src/Template.php on line 319", "code": 0, "file": "/app/vendor/twig/twig/src/Environment.php:262" } }, "level": 500, "level_name": "CRITICAL", "channel": "request", "datetime": "2023-09-28T13:11:19.762885+00:00", "extra": {} }
About this issue
- Original URL
- State: open
- Created 8 months ago
- Reactions: 6
- Comments: 24 (3 by maintainers)
Thanks for your attempt to solve this issue by replacing the Twig global variable by a Twig function. However, I don’t like that solution for two reasons:
eaglobal variableI talked with @dunglas about this. Two quick comments:
Symfony for example has a lot of
reset()calls which were introduced to make it compatible with apps like FrankenPHP in worker mode. See for example:But there are also examples where we removed the
reset()and replaced by a different solution:I tried to install FrankenPHP to reproduce the issue. I can’t even run my SF + EA apps with FrankenPHP, so I can’t reproduce it.
So, can anyone please give a shot to this proposal and see if we’re missing some reset somewhere? Thanks!
I’ve created a simple fix that should update globals if they are different.
I can’t test it in FrankenPHP at the moment, but I hope this will help. Additionally, it should be beneficial for any app servers where app states are persistent between requests (roadrunner,swoole, etc.).
Moreover, this fix will allow the use of subrequests in EasyAdmin.
Example concept:
It was unable due to issue with AdminContext in twig,
eavariable was the same for sub requests as for master request;Fix is just a simple listener for KernelView event:
@javiereguiluz any thoughts on moving the admin context from a global to a twig function and then deprecating the global?
Seems like it might fix this and is done pretty easily. Or is there a reason it’s a global?
Changing the event to
kernel.controllerfixed the menu matching issue. However I still come across rare situations where Twig globaleais not accessible. I’ll try to debug later. For now, the twig decorator hack works better for me.@mozkomor05 My fix is related to accessing the fresh AdminContext in Twig templates. Regarding the issue with the menu, as I see, menu highlighting is implemented in MenuItemMatcher. Therefore, it’s not related to the Twig context and uses AdminContextProvider to retrieve the context from the request. Maybe there is some another service that stores state (similar to Twig\Environment with globals);
UPD: An error might be caused if the
Twig\Environment::rendermethod is called before the kernel View event is fired.UPD2: After reviewing the EA flow again, I think it’s better to update globals after initializing AdminContext instead of waiting until the end of the request. So, I suggest changing the onKernelView event in my fix to onKernelRequest and registering the listener after AdminRouterSubscriber.
@misterx’s solution didn’t end up working for me. While this caused the bug to be less frequent (however, it still occurred in some marginal cases), it also caused the Admin Context in Twig to not match the context in the rest of the application in some situations, which led to highlighted menu items not matching the route, for example.
I came up with the following fix:
services.yamlApp\Service\Twig\Environment.phpThis does not change the fact that the solution is rather inelegant and the creators of EsayAdmin should, in my opinion, remove Twig Global and use an Twig Extension instead (e.g. replace
ea->ea()).@ac-shadow, I confirm that it comes from the frankenphp worker mode. But i liked the one container stuff, so I disabled it on the Dockerfile like this: (don’t know if there is a “proper” way)
I also encountered the same error using the latest version of https://github.com/dunglas/symfony-docker
Downgrading to 4.6.1 and adding the decorator class like @plantas mentioned worked for me but i wasn’t happy with that.
It seems to me that this issue is caused by the FrankenPHP server that is used in the docker configuration. Going back to an older version that used separated containers for php and caddy solved the issue for me. https://github.com/dunglas/symfony-docker/tree/b5710da39cc9939c2eef4787ab50b4ee7d16e44f