{"record":{"id":"8132c8d7c431db3a","repo":"symfony/routing","slug":"cannot-unserialize-loader-configurator","errorCode":null,"errorMessage":"Cannot unserialize Loader\\Configurator\\CollectionConfigurator","messagePattern":"Cannot unserialize Loader\\\\Configurator\\\\CollectionConfigurator","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"Loader/Configurator/CollectionConfigurator.php","lineNumber":48,"sourceCode":"    public function __construct(\n        private RouteCollection $parent,\n        string $name,\n        private ?self $parentConfigurator = null, // for GC control\n        private ?array $parentPrefixes = null,\n    ) {\n        $this->name = $name;\n        $this->collection = new RouteCollection();\n        $this->route = new Route('');\n    }\n\n    public function __serialize(): array\n    {\n        throw new \\BadMethodCallException('Cannot serialize '.__CLASS__);\n    }\n\n    public function __unserialize(array $data): void\n    {\n        throw new \\BadMethodCallException('Cannot unserialize '.__CLASS__);\n    }\n\n    public function __destruct()\n    {\n        if (null === $this->prefixes) {\n            $this->addPrefix($this->collection, $this->route->getPath(), $this->trailingSlashOnRoot);\n        }\n        if (null !== $this->host) {\n            $this->addHost($this->collection, $this->host);\n        }\n\n        $this->parent->addCollection($this->collection);\n    }\n\n    /**\n     * Creates a sub-collection.\n     */\n    final public function collection(string $name = ''): self","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/Loader/Configurator/CollectionConfigurator.php#L30-L66","documentation":"Companion to __serialize: unserializing a CollectionConfigurator would leave it in an invalid state (its __destruct depends on live prefixes), so __unserialize throws BadMethodCallException unconditionally.","triggerScenarios":"Calling unserialize() on data containing a CollectionConfigurator — e.g. cache/session payloads captured before the guard existed, or crafted serialized input.","commonSituations":"Stale cache entries from code that serialized configurators; restoring sessions that captured route builders; loading legacy payloads after upgrading the library.","solutions":["Purge the stale cache/session payloads containing CollectionConfigurator objects","Rebuild route configuration by calling the loader instead of unserializing","Clear any serialized object graphs that captured live configurators"],"exampleFix":"// before\n$cfg = unserialize($cached); // BadMethodCallException\n// after\n$routes = $attributeFileLoader->load('routes.php'); // rebuild instead","handlingStrategy":"try-catch","validationCode":"if (str_contains($payload, 'CollectionConfigurator')) { /* payload cannot be unserialized safely */ }","typeGuard":"function payloadSafeToUnserialize(string $payload): bool { return !str_contains($payload, 'CollectionConfigurator'); }","tryCatchPattern":"try { $value = unserialize($payload, ['allowed_classes' => false]); } catch (\\BadMethodCallException $e) { /* rebuild via loader */ }","preventionTips":["Purge caches after upgrading routing versions","Store RouteCollection or compiled route data, not builders","Use unserialize allowed_classes to fail fast on restricted graphs"],"tags":["serialization","unserialize","routing"],"backgroundTag":"unsupported-operation","analyzedSha":"83fa223250b50f4f018c011e101c330e65ac63cc","analyzedAt":"2026-09-14T03:19:46.280Z","contentChangedAt":"2026-09-14T03:19:46.280Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}