diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index 94563f7664129..a8c6a2e1a33ff 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -3548,11 +3548,6 @@
-
-
- getTypedValue($userId, $app, $key, $default ? 'true' : 'false', $lazy, ValueType::BOOL)]]>
-
-
request->server]]>
diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php
index 40e5a84d8b27f..2e2221ccfb92d 100644
--- a/lib/private/AppConfig.php
+++ b/lib/private/AppConfig.php
@@ -437,7 +437,15 @@ public function getValueFloat(string $app, string $key, float $default = 0, bool
*/
#[\Override]
public function getValueBool(string $app, string $key, bool $default = false, bool $lazy = false): bool {
- $b = strtolower($this->getTypedValue($app, $key, $default ? 'true' : 'false', $lazy, self::VALUE_BOOL));
+ // The explicit (string) cast and ?? null guard defend against a PHP OPcache bug where
+ // values passed by reference across function boundaries can have their type corrupted
+ // (e.g. bool returned as int, or null). Affects PHP 8.x with OPcache enabled; fixed
+ // upstream in https://github.com/php/php-src/pull/21973. Keep until minimum PHP version
+ // is bumped. Psalm sees the declared return type (string) and flags these as redundant.
+ /** @psalm-suppress RedundantCondition, TypeDoesNotContainNull */
+ $value = $this->getTypedValue($app, $key, $default ? 'true' : 'false', $lazy, self::VALUE_BOOL) ?? ($default ? 'true' : 'false');
+ /** @psalm-suppress RedundantCast */
+ $b = strtolower((string)$value);
return in_array($b, ['1', 'true', 'yes', 'on']);
}
diff --git a/lib/private/Config/UserConfig.php b/lib/private/Config/UserConfig.php
index 8c551afb5cc31..5ea22730b58d4 100644
--- a/lib/private/Config/UserConfig.php
+++ b/lib/private/Config/UserConfig.php
@@ -705,11 +705,15 @@ public function getValueBool(
bool $default = false,
bool $lazy = false,
): bool {
- // The explicit (string) cast guards against a PHP OPcache bug where values passed
- // by reference across function boundaries can have their type corrupted (e.g. bool
- // returned as int). Affects PHP 8.x with OPcache enabled; fixed upstream in
- // https://github.com/php/php-src/pull/21973. Keep until minimum PHP version is bumped.
- $b = strtolower((string)$this->getTypedValue($userId, $app, $key, $default ? 'true' : 'false', $lazy, ValueType::BOOL));
+ // The explicit (string) cast and ?? null guard defend against a PHP OPcache bug where
+ // values passed by reference across function boundaries can have their type corrupted
+ // (e.g. bool returned as int, or null). Affects PHP 8.x with OPcache enabled; fixed
+ // upstream in https://github.com/php/php-src/pull/21973. Keep until minimum PHP version
+ // is bumped. Psalm sees the declared return type (string) and flags these as redundant.
+ /** @psalm-suppress RedundantCondition, TypeDoesNotContainNull */
+ $value = $this->getTypedValue($userId, $app, $key, $default ? 'true' : 'false', $lazy, ValueType::BOOL) ?? ($default ? 'true' : 'false');
+ /** @psalm-suppress RedundantCast */
+ $b = strtolower((string)$value);
return in_array($b, ['1', 'true', 'yes', 'on']);
}