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

  1. Store the command description (command line, cwd, env, timeout) and rebuild with new Process() when needed
  2. Implement __sleep()/__serialize() on enclosing classes to exclude the Process property
  3. 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

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


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)