symfony/process · error · InvalidArgumentException
The environment block size
Error message
The environment block size (%d) exceeds the Windows limit of %d UTF-16 code units.
What it means
Symfony Process enforces the Windows CreateProcess limit on the environment block: the environment passed to a child process must fit within a maximum number of UTF-16 code units. This library joins all env pairs into a NUL-delimited block and measures its length (accounting for 4-byte UTF-8 sequences), throwing InvalidArgumentException when it exceeds self::WINDOWS_ENV_BLOCK_MAX_LENGTH.
Solutions
- Remove or shorten unnecessary environment variables before starting the process
- Pass an explicit smaller env array via Process::setEnv() or the constructor instead of merging the full inherited environment
- Split the work across multiple processes, or move large data out of env vars into files/arguments
- On non-Windows systems this limit is irrelevant; gate the env reduction behind PHP_OS_FAMILY checks if needed
Example fix
// before $process = new Process($cmd, null, array_merge(getenv(), $hugeExtraEnv)); $process->start(); // after $env = array_intersect_key(array_merge(getenv(), $hugeExtraEnv), array_flip(['PATH', 'HOME', 'TEMP'])); $process = new Process($cmd, null, $env); $process->start();
Defensive patterns
Strategy: validation
Validate before calling
$pairs = [];
foreach ($env as $k => $v) { $pairs[] = $k.'='.$v; }
$size = strlen(implode("\0", $pairs)) + count(preg_grep('/[\xF0-\xF4][\x80-\xBF]{3}/', $pairs));
if ($size > 32766) { $env = array_slice($env, 0, 10, true); } // trim before start() Try / catch
try { $process->start(); } catch (\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'environment block size')) { $process->setEnv($trimmedEnv); $process->start(); } else { throw $e; } } Prevention
- Keep child env minimal: pass only required vars instead of merging the full inherited environment
- Avoid storing payloads or config in environment variables on Windows
- Compute env block size in CI tests for Windows-targeted jobs
- Use files or arguments for large data instead of env vars
When it happens
Trigger: Calling start() (or run(), which calls start()) on Windows with an environment containing very long or very many variables so the joined env block exceeds WINDOWS_ENV_BLOCK_MAX_LENGTH.
Common situations: Inheriting a huge environment (CI systems with many variables), setting very long PATH or variable values, or adding large env entries via setEnv()/setDefaults() before launching a process on Windows.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- TTY mode is not supported on Windows platform.
- Unable to kill the process
- " " only accepts strings, Traversable objects or stream…
- Cannot serialize…
- Cannot unserialize…
AI-assisted analysis of symfony/process@99b85026db (2026-09-14).
Data as JSON: /api/errors/cbc76ea0cb50c295.
Report an issue: GitHub.
Appendix: source
Thrown at Process.php:1757
'SERVER_PROTOCOL', 'SERVER_SIGNATURE', 'SERVER_SOFTWARE',
], true)
) {
unset($env[$k]);
}
}
return $env;
}
private function validateWindowsEnvBlockSize(array $envPairs): void
{
$block = implode("\0", $envPairs)."\0";
@preg_replace('/./u', '', $block, -1, $blockLength)
?? preg_replace('/./', '', $block, -1, $blockLength);
$blockLength += 1 + preg_match_all('/[\xF0-\xF4][\x80-\xBF]{3}/', $block);
if ($blockLength > self::WINDOWS_ENV_BLOCK_MAX_LENGTH) {
throw new InvalidArgumentException(\sprintf('The environment block size (%d) exceeds the Windows limit of %d UTF-16 code units.', $blockLength, self::WINDOWS_ENV_BLOCK_MAX_LENGTH));
}
}
}
View on GitHub (pinned to 99b85026db)