[SOLVED] Acorn v3 -> v4 Upgrade | PSR Logger Issue -> Bedrock/WPML | Fatal error: Declaration of Monolog\Logger::emergency

Edit

  • This issue has been solved, the title has been updated to make this post easier to find for others.
  • Looking for a solution?
    • @alexmzk Provided a workaround below
    • @RistoKaalma pinpointed the issue in the WPML plugin and was marked as the solution for this thread

Original Post

As recommended by Log1x on my GitHub issue, I will try discourse to find a solution.

Summary
I have a project that’s kept up to dat using the latest bedrock, and sage theme. When I try to update acorn to v4.x only when my application is set to the development environment I am getting a fatal error caused by Monolog, a dependency to Illuminate Log.

Steps that got me to the error

  • Update the composer.json file to: "roots/acorn": "^4.0"
  • Run composer update "roots/acorn" -W

The Error

Fatal error: Declaration of Monolog\Logger::emergency(Stringable|string $message, array $context = []): void must be compatible with Psr\Log\LoggerInterface::emergency($message, array $context = []) in /Users/yasser/Artcore/artcore_bedrock_sofico_website/vendor/monolog/monolog/src/Monolog/Logger.php on line 681

Stacktrace

Fatal error: Uncaught Error: Class "Monolog\Logger" not found in 
/Users/yasser/project/my_project/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php:60 
Stack trace: 
- 0 /Users/yasser/project/my_project/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php(38): Monolog\Handler\AbstractHandler->setLevel(Object(Monolog\Level)) 
- 1 /Users/yasser/project/my_project/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php(49): Monolog\Handler\AbstractHandler->__construct(Object(Monolog\Level), true) 
- 2 /Users/yasser/project/my_project/vendor/illuminate/log/LogManager.php(189): Monolog\Handler\StreamHandler->__construct('/Users/yasser/M...', Object(Monolog\Level)) 
- 3 /Users/yasser/project/my_project/vendor/illuminate/log/LogManager.php(141): Illuminate\Log\LogManager->createEmergencyLogger() 
- 4 /Users/yasser/project/my_project/vendor/illuminate/log/LogManager.php(124): Illuminate\Log\LogManager->get('stack') 
- 5 /Users/yasser/project/my_project/vendor/illuminate/log/LogManager.php(681): Illuminate\Log\LogManager->driver() 
- 6 /Users/yasser/project/my_project/vendor/roots/acorn/src/Illuminate/Foundation/Exceptions/Handler.php(317): Illuminate\Log\LogManager->error('Declaration of ...', Array) 
- 7 /Users/yasser/project/my_project/vendor/roots/acorn/src/Illuminate/Foundation/Exceptions/Handler.php(278): Illuminate\Foundation\Exceptions\Handler->reportThrowable(Object(Symfony\Component\ErrorHandler\Error\FatalError)) 
- 8 /Users/yasser/project/my_project/vendor/roots/acorn/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(183): Illuminate\Foundation\Exceptions\Handler->report(Object(Symfony\Component\ErrorHandler\Error\FatalError)) 
- 9 /Users/yasser/project/my_project/vendor/roots/acorn/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(231): Illuminate\Foundation\Bootstrap\HandleExceptions->handleException(Object(Symfony\Component\ErrorHandler\Error\FatalError)) 
- 10 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->handleShutdown() 
- 11 {main} thrown in /Users/yasser/project/my_project/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php on line 60

Anyone has any ideas on how to resolve this?

Thanks in advance!

  • Y

Hi, I had the same problem, in my case the error was that a plugin loaded its PSR Log package as global and replaced the one loaded via composer

I was able to identify the problem by entering

var_dump(class_exists('Psr\Log\LoggerInterface'), (new \ReflectionClass('Psr\Log\LoggerInterface'))->getFileName());

In my bedrock-autoloader.php, this way I realized that the project was loading the package from a different folder than the vendor’s.

I hope this helps you.

1 Like

Thank you pcatapan for your answer!

Unfortunately, the class does ‘not exist’, yet it loads it.

Here’s the output from that var_dump()

bool(false) string(91) "/Users/yasser/project/my_project/vendor/psr/log/src/LoggerInterface.php" 
  • The interface does exist within my vendor folder

  • The weird fact is that everything runs fine when I run the project setup with the production environment.

  • When I just add var_dump(class_exists('Psr\Log\LoggerInterface')); before the Autoloader in bedrock-autoloader.php is instantiated. I get a dump saying bool(false) but no more error…

As I understand now, and from various searches. This could have something to do with a php-psr extension. But I have no psr extensions installed.

I’ve found several people and threads about this issue. most blaming psr extensions. Though I have none installed.

Some urls for context

So I really feel like it has something to do with a wrong Psr version? yet I am not requiring any PSR in my composer.json

@yasser_artcore I have the same problem as you, but in my case, the WooCommerce Germanized Plugin is causing the issue by including an old version of PSR.

So far, I don’t have a solution for this other than deactivating the plugin in development and only activating it in staging and production. :confused:

EDIT
I ended up disabling error reporting for the plugin folder in the development environment with a mu-plugin:

<?php
/*
Plugin Name: Error Handler
Description: Sets a custom error handler to disable error reporting for WP_PLUGIN_DIR in the development environment.
*/

if (defined('WP_ENV') && WP_ENV === 'development') {
    set_error_handler('plugin_error_handler');
    add_action('admin_notices', 'error_handler_admin_notice');
}

function plugin_error_handler($errno, $errstr, $errfile, $errline)
{
    $excluded_paths = [
        WP_PLUGIN_DIR,
    ];

    foreach ($excluded_paths as $path) {
        if (strpos($errfile, $path) !== false) {
            return true;
        }
    }

    return true;
}

function error_handler_admin_notice()
{
    $class = 'notice notice-warning';
    $message = 'The Error Handler plugin is activated and disables error reporting for: ' . WP_PLUGIN_DIR;

    printf('<div class="%s"><p>%s</p></div>', esc_attr($class), esc_html($message));
}

@yasser_artcore are you using:

  1. Bedrock
  2. WPML

In general, if you are using WPML plugin, try commenting out the following part (~ line 65):

# wpml-multilingual-cms/vendor/composer/autoload_static.php
'Psr\\Log\\' => 
    array (
        0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
    ),

Does it change anything?

@alexmzk , Thanks for your reply!

You helped a lot, thank you for the example. It does prove that it’s probably plugin related code .

Love the solution you found!


@RistoKaalma Amazing! You nailed it :smiley:

It is indeed WPML and your solution fixed it! Thanks a lot!


Unfortunately as this time, even the latest version of WPML has this issue. I’ll open a support thread with them

1 Like

Perhaps you don’t need to start a duplicate support thread on WPML - fellow Roots.io members are on it already:

  1. Fatal error: Declaration of Monolog - WPML
  2. https://github.com/mollie/WooCommerce/issues/892

When using Bedrock for managing plugins with composer, composer-patches (shout-out to @tombro for the suggestion) might be useful until WPML v4.7 is released.

In Bedrock dir:

  1. Run composer require cweagans/composer-patches
  2. Add to "config""allow-plugins" in in composer.json:
[...],
"cweagans/composer-patches": true
  1. Add to "extra" in composer.json:
[...],
"patches": {
      "wpml/wpml-multilingual-cms": {
        "Fix monolog": "patches/wpml-multilingual-cms/monolog-fix.patch"
      }
    }
  1. Write to patches/wpml-multilingual-cms/monolog-fix.patch file:
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -62,10 +62,10 @@
         array (
             0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
         ),
-        'Psr\\Log\\' => 
-        array (
-            0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
-        ),
+        // 'Psr\\Log\\' => 
+        // array (
+        //     0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+        // ),
         'PhpMyAdmin\\SqlParser\\' => 
         array (
             0 => __DIR__ . '/..' . '/wpml/sql-parser/src',
  1. Manually delete web/app/plugins/wpml-multilingual-cms dir

For me, seemingly it only ran when a plugin is being initially installed (or maybe updated… ultimately the state needs to “change” for it to work) - thus I had to manually delete the existing plugin files.

  1. Run composer update - my output:
xxx@yyy:~/Projects/example-web/site$ composer update
Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies                                 
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
Gathering patches for root package.
Gathering patches for dependencies. This might take a minute.
  - Installing wpml/wpml-multilingual-cms (4.6.9): Extracting archive
  - Applying patches for wpml/wpml-multilingual-cms
    patches/wpml-multilingual-cms/monolog-fix.patch (Fix monolog)

Generating optimized autoload files
> Roots\Acorn\ComposerScripts::postAutoloadDump
68 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found

Another incompatible plugin Logger interface incompatible with Psr\Log\LoggerTrait:log() (968) · Issue #1518 · woocommerce/woocommerce-paypal-payments · GitHub