symfony/process · error · BadMethodCallException

Cannot unserialize Symfony\Component\Process\Process

Error message

Cannot unserialize Symfony\Component\Process\Process

What it means

Process::__unserialize() is the symmetric guard: unserialize() must never reconstruct a Process object because it would refer to a dead/unknown OS process and invalid pipe handles; it always throws BadMethodCallException.

Solutions

  1. Stop embedding Process objects in serialized payloads; store process descriptions instead
  2. Unserialize with ['allowed_classes' => false] or a strict whitelist
  3. Purge/invalidate caches and queues holding serialized Process instances

Example fix

// before
$task = unserialize($queueMessage);
// after
$task = unserialize($queueMessage, ['allowed_classes' => false]);
Defensive patterns

Strategy: type-guard

Validate before calling

$data = unserialize($blob, ['allowed_classes' => false]);

Type guard

function safeUnserialize(string $blob): mixed { return unserialize($blob, ['allowed_classes' => false]); }

Try / catch

try { $obj = unserialize($blob); } catch (\BadMethodCallException $e) { $obj = Process::fromShellCommandline($blob['command']); }

Prevention

When it happens

Trigger: unserialize() of any payload containing a Symfony Process object — stale cache/session data, old queue messages, or attacker-controlled serialized input.

Common situations: Migrating code that used to (incorrectly) serialize Processes, loading old cache entries, processing untrusted serialized blobs.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of symfony/process@99b85026db (2026-09-14). Data as JSON: /api/errors/4846019831dc7fb6. Report an issue: GitHub.

Appendix: source

Thrown at Process.php:223

     *
     * @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()
    {
        $this->resetProcessData();
    }

    /**
     * Runs the process.

View on GitHub (pinned to 99b85026db)