{"record":{"id":"1c7a1af9095b4287","repo":"symfony/routing","slug":"cannot-unserialize-loader-configurator-importconfigurator","errorCode":null,"errorMessage":"Cannot unserialize Loader\\Configurator\\ImportConfigurator","messagePattern":"Cannot unserialize Loader\\\\Configurator\\\\ImportConfigurator","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"Loader/Configurator/ImportConfigurator.php","lineNumber":39,"sourceCode":"    use Traits\\HostTrait;\n    use Traits\\PrefixTrait;\n    use Traits\\RouteTrait;\n\n    public function __construct(\n        private RouteCollection $parent,\n        RouteCollection $route,\n    ) {\n        $this->route = $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        $this->parent->addCollection($this->route);\n    }\n\n    /**\n     * Sets the prefix to add to the path of all child routes.\n     *\n     * @param string|array $prefix the prefix, or the localized prefixes\n     *\n     * @return $this\n     */\n    final public function prefix(string|array $prefix, bool $trailingSlashOnRoot = true): static\n    {\n        $this->addPrefix($this->route, $prefix, $trailingSlashOnRoot);\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/Loader/Configurator/ImportConfigurator.php#L21-L57","documentation":"The matching __unserialize() of ImportConfigurator also unconditionally throws BadMethodCallException. Since __serialize() always throws, no valid serialized representation exists; unserializing data into ImportConfigurator is always invalid.","triggerScenarios":"unserialize() on a payload containing an ImportConfigurator object (e.g. cache/session data that captured one via nested references), or injecting a serialized object string into the app.","commonSituations":"Restoring stale cache files that captured configurator objects, unserializing user-supplied data that references this class, moving session data between environments.","solutions":["Remove ImportConfigurator instances from any serialized payload; store route definitions or the built RouteCollection instead.","Purge/regenerate cache and session data containing these objects.","Rebuild routing configuration at runtime from its config files rather than deserializing objects."],"exampleFix":"// before\n$config = unserialize($cached);\n// after\n$collection = new RouteCollection();\n(new RoutingConfigurator($collection))->import($file);","handlingStrategy":"validation","validationCode":"$isSafe = array_reduce($payloadClasses, fn($ok, $c) => $ok && $c !== \\Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator::class, true);","typeGuard":"function safeToUnserialize(array $allowed, string $class): bool { return in_array($class, $allowed, true) && $class !== \\Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator::class; }","tryCatchPattern":"try { $o = unserialize($data, ['allowed_classes' => false]); } catch (\\Exception $e) { /* regenerate routing config */ }","preventionTips":["Use unserialize($data, ['allowed_classes' => [...]]) allowlists.","Never capture configurator objects in serialized state.","Regenerate routes from files rather than restoring serialized objects."],"tags":["routing","unserialization","bad-method-call","symfony"],"backgroundTag":"json-unmarshal-failed","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"}