Problem
WP-Stateless ships psr/simple-cache v3.0.0 in its vendor/ directory, which defines CacheInterface with native PHP 8 type declarations:
// psr/simple-cache v3 — shipped by wp-stateless
public function get(string $key, mixed $default = null): mixed;
Any other plugin that implements Psr\SimpleCache\CacheInterface against v1 (no native types) will fatal when both plugins are active, because the Jetpack autoloader loads the highest available version globally:
PHP Fatal error: Declaration of WordPress_Simple_Cache::get($key, $default = null)
must be compatible with Psr\SimpleCache\CacheInterface::get(string $key, mixed $default = null): mixed
This was observed in production with WP Ultimo's SSO cache class, but any plugin implementing PSR-16 v1 will hit the same conflict.
Root cause
psr/simple-cache is a transitive dependency (brianhenryie/strauss → json-mapper/json-mapper → psr/simple-cache). All upstream packages accept ^1.0 || ^2.0 || ^3.0, so Composer resolves to v3. The vendored Psr\SimpleCache\CacheInterface class is then loaded into the global namespace, where it conflicts with any other plugin's v1-compatible implementation.
This is not specific to psr/simple-cache — the same class of conflict can occur with any shared PSR interface or common library (e.g., psr/log, psr/container, monolog/monolog, guzzlehttp/guzzle) where wp-stateless ships a different major version than another active plugin.
Suggested fix
Use PHP-Scoper or expand the existing Strauss configuration to prefix all vendor namespaces under a plugin-specific prefix (e.g., wpCloud\StatelessMedia\). This is the standard approach for WordPress plugins that ship Composer dependencies — it isolates vendor classes entirely and eliminates cross-plugin autoloader conflicts.
wp-stateless already has Strauss configured in composer.json, but currently only prefixes deliciousbrains/wp-background-processing. Expanding it to cover all packages in vendor/ (particularly PSR interfaces, Symfony components, Monolog, and Guzzle) would prevent this entire class of conflict.
Workaround
Pinning "psr/simple-cache": "^1.0" in composer.json resolves the immediate conflict by forcing v1 (no native types), which is compatible with both wp-stateless's own dependencies and other plugins' v1-style implementations. However, this is a band-aid — the underlying namespace collision risk remains for every other shared library.
Environment
- WordPress: 6.8
- PHP: 8.2
- WP-Stateless: latest develop branch
- Conflicting plugin: WP Ultimo (any plugin implementing PSR-16 v1 will trigger it)
Problem
WP-Stateless ships
psr/simple-cachev3.0.0 in itsvendor/directory, which definesCacheInterfacewith native PHP 8 type declarations:Any other plugin that implements
Psr\SimpleCache\CacheInterfaceagainst v1 (no native types) will fatal when both plugins are active, because the Jetpack autoloader loads the highest available version globally:This was observed in production with WP Ultimo's SSO cache class, but any plugin implementing PSR-16 v1 will hit the same conflict.
Root cause
psr/simple-cacheis a transitive dependency (brianhenryie/strauss→json-mapper/json-mapper→psr/simple-cache). All upstream packages accept^1.0 || ^2.0 || ^3.0, so Composer resolves to v3. The vendoredPsr\SimpleCache\CacheInterfaceclass is then loaded into the global namespace, where it conflicts with any other plugin's v1-compatible implementation.This is not specific to
psr/simple-cache— the same class of conflict can occur with any shared PSR interface or common library (e.g.,psr/log,psr/container,monolog/monolog,guzzlehttp/guzzle) where wp-stateless ships a different major version than another active plugin.Suggested fix
Use PHP-Scoper or expand the existing Strauss configuration to prefix all vendor namespaces under a plugin-specific prefix (e.g.,
wpCloud\StatelessMedia\). This is the standard approach for WordPress plugins that ship Composer dependencies — it isolates vendor classes entirely and eliminates cross-plugin autoloader conflicts.wp-stateless already has Strauss configured in
composer.json, but currently only prefixesdeliciousbrains/wp-background-processing. Expanding it to cover all packages invendor/(particularly PSR interfaces, Symfony components, Monolog, and Guzzle) would prevent this entire class of conflict.Workaround
Pinning
"psr/simple-cache": "^1.0"incomposer.jsonresolves the immediate conflict by forcing v1 (no native types), which is compatible with both wp-stateless's own dependencies and other plugins' v1-style implementations. However, this is a band-aid — the underlying namespace collision risk remains for every other shared library.Environment