Making a separate post because I’m still getting this error with 1.22.4:
PHP Fatal error: Cannot redeclare GuzzleHttp\describe_type() (previously declared in .../wp-content/themes/.../vendor/guzzlehttp/guzzle/src/functions.php:16) in .../wp-content/plugins/updraftplus/vendor/guzzlehttp/guzzle/src/functions.php on line 41
This indicates that your theme includes a copy of the Guzzle HTTP library, and that it’s a version which conflicts with the one in UpdraftPlus. Is your theme up-to-date? If so, can you ask the supplier what version of Guzzle they have in it? (And why – it’s a strange thing to have in a theme; WordPress already has HTTP functions, so a further library is only normally needed for specialised usage, e.g. UpdraftPlus includes the Amazon AWS toolkit for accessing S3).
Putting this early in your
wp-config.phpfile may work around it:
>> it’s a strange thing to have in a theme
Well not in my case. My theme uses composer packages. It just happens that one of them used guzzlehttp. I replaced the package with a different one that does not depend on guzzlehttp, so the issue is gone.
But there must be a way on your side to ensure that it will pick the packages installed under your plugin directory. It’s only a matter of time before you ran into a situation where another plugin also uses one of your packages but with a different version. There must be a way out of this mess. Maybe the answer is prefixing, not sure.
Some food for thoughts taken from https://www.smashingmagazine.com/2019/03/composer-wordpress/:
If two different plugins bundle different versions of a same library which are incompatible with each other, and these two plugins are installed on the same site, it could cause the site to malfunction. A solution to this issue is to modify the dependencies’ namespace to some custom namespace, which ensures that different versions of the same library, by having different namespaces, are treated as different libraries. This can be achieved through a custom script or through Mozart, a library which composes all dependencies as a package inside a WordPress plugin.
If things were as simple as adjusting name-spacing, that would be fantastic. Unfortunately, the conflicts fixed in 1.22.4 were actually *caused* by name-spacing – another plugin with 200,000 installs (and a few others) had done it wrongly, and thereby introduced a conflict where there wouldn’t have been one. Also, we’ve participated in the Mozart issue tracker over recent years to try to iron out issues, but ultimately concluded that it wasn’t ready for use in our projects yet (you’ll see that it says at that link “This package is very experimental … always wear a helmet when using this in production environments”).
The real solution is for other users of popular libraries (like Guzzle) to do what UpdraftPlus does:
1. Don’t load the library until the latest point at which you’re going to use it (in our case, when we’re about to contact Amazon S3), instead of auto-loading it on every page load. There’s no scenario in which a front-end theme and a back-end backup plugin should both be wanting to load Guzzle inside the same PHP invocation.
2. Keep libraries up to date. Here, there’s a problem that older and newer versions of the AWS library are mutually incompatible, despite semantic versionning indicating that they should be compatible. That’s unfortunate, but sadly happens since even AWS’s coders aren’t perfect – but if both projects kept versions of the AWS library up to date, the conflict would be avoided.
Hi David, many thanks for your detailed reply and the education, really appreciate it 🙂
I did see the Mozart ‘experimental’ warning. I was thinking I should look into it for my theme, so it’s good to get your take on it. I also saw a mention of PHP-Scoper but it sounded heavy-handed.
1. My theme does that. Class files are loaded when needed. In my case, I had to do some DOM manipulation to work around how a plugin was laying out the page and decided to use a PHP HTML Parser for this. It just happened the parser I picked was dependent on guzzlehttp/psr7, and I haven’t looked into why. I was just thankful such a package existed. So there was a scenario in my case. Themes are not always front-end only. The one I now switched to does not depends on the guzzlehttp package anymore.
2. Agreed. I try my best to keep plugins/themes and npm/composer packages up-to-date. It is a bit relentless and in case of package version conflicts, it seems that we’re leaving this to luck still at the moment. Which is not how I want to build software.
I’m glad your issue got fixed as is now mine. Best of luck with the future possible conflicts. I know the plugins owner’s life is not a restful one.
Just for completeness, the PHP HTML Parser uses the guzzlehttp library for its loadFromUrl function here:
and I see it uses both guzzlehttp/psr7 and guzzlehttp/client. Maybe ideally they could have put this code in a different class.
- The topic ‘PHP Fatal error: Cannot redeclare GuzzleHttp\describe_type()’ is closed to new replies.