symfony/process · error · BadMethodCallException

Cannot unserialize…

Error message

Cannot unserialize Symfony\Component\Process\Pipes\WindowsPipes

What it means

WindowsPipes uses temporary files as pipe buffers and cannot be serialized; __unserialize() is a sentinel that always throws BadMethodCallException whenever a serialized WindowsPipes instance is unserialized, so serialization round-trips of this object are unsupported by design.

Solutions

  1. Recreate the Process from stored configuration instead of unserializing it
  2. Use unserialize() with ['allowed_classes' => false] or explicit class whitelist to avoid instantiating pipes
  3. Purge old cache entries containing Process objects

Example fix

// before
$data = unserialize($cached);
// after
$data = unserialize($cached, ['allowed_classes' => [\stdClass::class]]);
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 = null; }

Prevention

When it happens

Trigger: unserialize() on data containing a WindowsPipes object — from stale caches, crafted payloads, or payloads created before this guard existed.

Common situations: Restoring cached sessions on Windows that embedded live Process objects; handling untrusted serialized input.

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/2a7d15614442920b. Report an issue: GitHub.

Appendix: source

Thrown at Pipes/WindowsPipes.php:97

                    $this->fileHandles[$pipe] = $h;
                    $this->files[$pipe] = $file;
                }
                break;
            }
            restore_error_handler();
        }

        parent::__construct($input);
    }

    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()
    {
        $this->close();
    }

    public function getDescriptors(): array
    {
        if (!$this->haveReadSupport) {
            $nullstream = fopen('NUL', 'c');

            return [
                ['pipe', 'r'],
                $nullstream,
                $nullstream,
            ];
        }

View on GitHub (pinned to 99b85026db)