yiisoft/yii2 · error · InvalidArgumentException
Expected actual value to be a string,
Error message
Expected actual value to be a string,
What it means
Thrown by yii\base\Security::compareString() when the $actual argument (the user-supplied side of the comparison) is not a PHP string. hash_equals() requires both parameters to be strings, so the method validates each with is_string() and reports the actual gettype() in the message, e.g. 'Expected actual value to be a string, NULL given.'
Source
Thrown at framework/base/Security.php:551
return $salt;
}
/**
* Performs string comparison using timing attack resistant approach.
* @see https://codereview.stackexchange.com/q/13512
* @param string $expected string to compare.
* @param string $actual user-supplied string.
* @return bool whether strings are equal.
*/
public function compareString($expected, $actual)
{
if (!is_string($expected)) {
throw new InvalidArgumentException('Expected expected value to be a string, ' . gettype($expected) . ' given.');
}
if (!is_string($actual)) {
throw new InvalidArgumentException('Expected actual value to be a string, ' . gettype($actual) . ' given.');
}
return hash_equals($expected, $actual);
}
/**
* Masks a token to make it uncompressible.
* Applies a random mask to the token and prepends the mask used to the result making the string always unique.
* Used to mitigate BREACH attack by randomizing how token is outputted on each request.
* @param string $token An unmasked token.
* @return string A masked token.
* @since 2.0.12
*/
public function maskToken($token)
{
// The number of bytes in a mask is always equal to the number of bytes in a token.
$mask = $this->generateRandomKey(StringHelper::byteLength($token));
return StringHelper::base64UrlEncode($mask . ($mask ^ $token));View on GitHub (pinned to 66f00d18a2)
Solutions
- Normalize request input before comparing: cast to string or use ->get('X-Token', '') with an empty-string default.
- Treat a missing token as a mismatch, not an exception: if (!is_string($token)) { return false; } before calling compareString().
- Validate the shape of decoded JSON payloads (e.g. Yii2 validator with 'string' rule) before using fields in comparisons.
Example fix
// before
$valid = Yii::$app->security->compareString($expectedSignature, $request->headers->get('X-Signature'));
// header absent -> headers->get() returns null -> InvalidArgumentException
// after
$signature = (string) $request->headers->get('X-Signature', '');
$valid = $signature !== '' && Yii::$app->security->compareString($expectedSignature, $signature); Defensive patterns
Strategy: type-guard
Validate before calling
// Normalize request input before comparing
$token = $request->headers->get('X-Token', '');
$token = is_string($token) ? $token : '';
if ($token === '') {
return false; // missing token is a mismatch, not an exception
}
return Yii::$app->security->compareString($expectedToken, $token); Type guard
function requestTokenToString($value): ?string
{
return is_string($value) && $value !== '' ? $value : null;
} Prevention
- Use empty-string defaults when reading headers/cookies/JSON fields used in comparisons
- Validate request payload shapes (string rules) before touching security-sensitive values
- Cast user-supplied scalars to string once at the boundary, not at each comparison
When it happens
Trigger: Passing a value read with a null default as $actual: Yii::$app->request->headers->get('X-Token') when the header is absent; $_COOKIE value via ArrayHelper::getValue($_COOKIE, 'key') returning null; a JSON body field that is a number/object instead of a string; casting mistakes where an array of tokens is passed instead of one token.
Common situations: CSRF/auth-token checks against optional request headers or cookies that may legitimately be missing; API clients sending numeric tokens that json_decode() turns into ints; file-upload or webhook handlers receiving structured JSON where a scalar was expected.
Related errors
- Expected expected value to be a string,
- Encryption requires the OpenSSL PHP extension
- {cipher} is not an allowed cipher
- Invalid parameters to hash_hkdf()
- Invalid parameters to hash_pbkdf2()
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/6c41d020e80592d8.
Report an issue: GitHub.