symfony/http-foundation · error · InvalidArgumentException
Cannot anonymize less than 0 bytes.
Error message
Cannot anonymize less than 0 bytes.
What it means
IpUtils::anonymize() truncates IP addresses for GDPR-style anonymization. The $v4Bytes and $v6Bytes parameters are documented as int<0,4> and int<0,16>; passing a negative byte count would mean removing more bits than the address has or producing nonsensical output, so the method throws this InvalidArgumentException before doing any work.
Solutions
- Clamp the values: $v4Bytes = max(0, min(4, $v4Bytes)); $v6Bytes = max(0, min(16, $v6Bytes));
- Validate user/config-supplied byte counts before calling anonymize and reject negatives.
- Pass 0 explicitly if you want no truncation (0 is a legal value).
- Use native PHP types (int<0,4>) with static analysis to catch negatives before runtime.
- Log the offending input value to find which config source produced the negative number.
Example fix
// before IpUtils::anonymize($ip, $configBytes); // $configBytes = -1: throws // after $v4 = max(0, min(4, $configBytes)); $v6 = max(0, min(16, $configBytes)); IpUtils::anonymize($ip, $v4, $v6);
Defensive patterns
Strategy: validation
Validate before calling
// before calling anonymize
$v4Bytes = max(0, (int) $v4Bytes);
$v6Bytes = max(0, (int) $v6Bytes);
if ($v4Bytes < 0 || $v6Bytes < 0) {
throw new \InvalidArgumentException('Byte counts must be non-negative.');
} Type guard
function isValidAnonymizeBytes(int $v4, int $v6): bool {
return $v4 >= 0 && $v4 <= 4 && $v6 >= 0 && $v6 <= 16;
} Try / catch
try {
$anon = IpUtils::anonymize($ip, $v4Bytes, $v6Bytes);
} catch (\InvalidArgumentException $e) {
$anon = IpUtils::anonymize($ip); // safe defaults (1 byte v4, 8 bytes v6)
} Prevention
- Clamp config-derived byte counts with max(0, ...) before calling.
- Use native int<0,4> / int<0,16> docblock types and static analysis.
- Validate environment/yaml privacy settings at config-load time, not at request time.
- Remember 0 is legal (no truncation); negatives never are.
When it happens
Trigger: Calling IpUtils::anonymize($ip, -1) or IpUtils::anonymize($ip, 4, -8); computing a byte count from unvalidated config (e.g. a privacy setting that can go negative) and passing it through.
Common situations: Config values like 'anonymize_bytes: -1' read from yaml/env and cast to int without validation; arithmetic that underflows (e.g. $bytes = $userSetting - $extra); tests probing boundary behavior.
Related errors
- Cannot anonymize more than 4 bytes for IPv4 and 16 bytes…
- The "sameSite" parameter value is not valid.
- The cookie name " " uses a reserved prefix, which requires…
- The cookie name " " uses the "__Host-" prefix, which…
- The cookie name " " uses the "__Host-" prefix, which…
AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13).
Data as JSON: /api/errors/d786789919715880.
Report an issue: GitHub.
Appendix: source
Thrown at IpUtils.php:210
return self::setCacheResult($cacheKey, false);
}
}
return self::setCacheResult($cacheKey, true);
}
/**
* Anonymizes an IP/IPv6.
*
* Removes the last bytes of IPv4 and IPv6 addresses (1 byte for IPv4 and 8 bytes for IPv6 by default).
*
* @param int<0, 4> $v4Bytes
* @param int<0, 16> $v6Bytes
*/
public static function anonymize(string $ip, int $v4Bytes = 1, int $v6Bytes = 8): string
{
if ($v4Bytes < 0 || $v6Bytes < 0) {
throw new \InvalidArgumentException('Cannot anonymize less than 0 bytes.');
}
if ($v4Bytes > 4 || $v6Bytes > 16) {
throw new \InvalidArgumentException('Cannot anonymize more than 4 bytes for IPv4 and 16 bytes for IPv6.');
}
/*
* If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007
* In that case, we only care about the part before the % symbol, as the following functions, can only work with
* the IP address itself. As the scope can leak information (containing interface name), we do not want to
* include it in our anonymized IP data.
*/
if (str_contains($ip, '%')) {
$ip = substr($ip, 0, strpos($ip, '%'));
}
$wrappedIPv6 = false;
if (str_starts_with($ip, '[') && str_ends_with($ip, ']')) {View on GitHub (pinned to 5aea19cd67)