symfony/process · error · BadMethodCallException
Cannot serialize Symfony\Component\Process\Process
Error message
Cannot serialize Symfony\Component\Process\Process
What it means
A Symfony Process object wraps an OS process, pipes, and mutable runtime state, none of which survives PHP serialization. Process::__serialize() therefore unconditionally throws BadMethodCallException to stop serialize() rather than producing a broken object.
Solutions
- Store the command description (command line, cwd, env, timeout) and rebuild with new Process() when needed
- Implement __sleep()/__serialize() on enclosing classes to exclude the Process property
- Use a serializable value object (e.g. an id) and keep a process registry keyed by that id
Example fix
// before $payload = serialize(['process' => $process]); // after $payload = serialize(['commandline' => $process->getCommandLine(), 'cwd' => $process->getWorkingDirectory()]);
Defensive patterns
Strategy: type-guard
Validate before calling
if ($obj instanceof \Symfony\Component\Process\Process) { throw new \LogicException('Process objects are not serializable'); } Type guard
function isSerializable(mixed $v): bool { try { serialize($v); return true; } catch (\Throwable) { return false; } } Try / catch
try { $payload = serialize($task); } catch (\BadMethodCallException $e) { $payload = serialize($task->getDescriptor()); } Prevention
- Never store Process objects in session/cache/queue payloads
- Use getCommandLine(), cwd and env as the serializable descriptor
- Run a serialize() smoke test in unit tests for cacheable classes
When it happens
Trigger: serialize($process), serialize() of an object holding a Process property (job/task objects, cache entries, session data), or passing a running Process through serialize-based transports.
Common situations: Storing pending/running tasks in cache or session with the Process embedded, serialize-based logging/debugging, legacy queue payloads containing Process instances.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Cannot serialize Symfony\Component\Process\Pipes\UnixPipes
- Cannot unserialize Symfony\Component\Process\Pipes\UnixPipes
- Cannot serialize…
- Cannot unserialize…
- Cannot unserialize Symfony\Component\Process\Process
AI-assisted analysis of symfony/process@99b85026db (2026-09-14).
Data as JSON: /api/errors/5a58257062e56ac0.
Report an issue: GitHub.
Appendix: source
Thrown at Process.php:218
* @param string $command The command line to pass to the shell of the OS
* @param string|null $cwd The working directory or null to use the working dir of the current PHP process
* @param EnvArray|null $env The environment variables or null to use the same environment as the current PHP process
* @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input
* @param int|float|null $timeout The timeout in seconds or null to disable
*
* @throws LogicException When proc_open is not installed
*/
public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
{
$process = new static([], $cwd, $env, $input, $timeout);
$process->commandline = $command;
return $process;
}
public function __serialize(): array
{
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
}
public function __unserialize(array $data): void
{
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
}
public function __destruct()
{
if ($this->options['create_new_console'] ?? false) {
$this->processPipes->close();
} else {
$this->stop(0);
}
}
public function __clone()
{View on GitHub (pinned to 99b85026db)