{"record":{"id":"0ed1b28fdd1d2288","repo":"doctrine/instantiator","slug":"could-not-produce-an-instance-of-s-via-un-seria","errorCode":null,"errorMessage":"Could not produce an instance of \"%s\" via un-serialization, since an error was triggered in file \"%s\" at line \"%d\"","messagePattern":"Could not produce an instance of \"(.+?)\" via un-serialization, since an error was triggered in file \"(.+?)\" at line \"(.+?)\"","errorType":"exception","errorClass":"Doctrine\\Instantiator\\Exception\\UnexpectedValueException","httpStatus":null,"severity":"error","filePath":"src/Exception/UnexpectedValueException.php","lineNumber":51,"sourceCode":"            $exception,\n        );\n    }\n\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    public static function fromUncleanUnSerialization(\n        ReflectionClass $reflectionClass,\n        string $errorString,\n        int $errorCode,\n        string $errorFile,\n        int $errorLine,\n    ): self {\n        return new self(\n            sprintf(\n                'Could not produce an instance of \"%s\" via un-serialization, since an error was triggered '\n                . 'in file \"%s\" at line \"%d\"',\n                $reflectionClass->getName(),\n                $errorFile,\n                $errorLine,\n            ),\n            0,\n            new Exception($errorString, $errorCode),\n        );\n    }\n}\n","sourceCodeStart":33,"sourceCodeEnd":62,"githubUrl":"https://github.com/doctrine/instantiator/blob/cbb879d6eea7ce605d95f4c455679df73ee682ea/src/Exception/UnexpectedValueException.php#L33-L62","documentation":"During the unserialization fallback, the instantiator installs a temporary error handler around a probe unserialize() (src/Instantiator.php:169-179). Any PHP notice/warning raised during that probe — as opposed to a thrown Exception — is converted by fromUncleanUnSerialization() into this message, which reports the file and line where the PHP error fired, with the raw warning text and code chained in the previous exception. The cause is code executed during unserialization (Serializable::unserialize(), __wakeup(), __unserialize()) or PHP itself emitting diagnostics on the synthetic empty payload.","triggerScenarios":"instantiate() takes the unserialize fallback and the probe raises a PHP error that the handler at src/Instantiator.php:169 captures: a __wakeup() reading an undefined index/property on the empty synthetic payload, a deprecation notice triggered inside unserialize(), or unserialize() itself warning about the payload for classes with internal ancestors (e.g. ArrayObject/ArrayIterator subclasses with 'Erroneous data format for class').","commonSituations":"Subclasses of internal serializable SPL classes (ArrayObject, ArrayIterator, SplStack) whose synthetic payload is not valid for the internal parent; __wakeup() implementations that dereference keys the empty payload never set; code emitting deprecation notices under newer PHP versions during unserialization; noisy autoloaders or custom error-to-exception converters that emit diagnostics while the probe runs.","solutions":["Read the message: it names the exact file and line of the PHP error, and getPrevious() carries the raw warning string and error code — fix the code at that location first.","Make __wakeup()/Serializable::unserialize()/__unserialize() safe for an empty payload: null-coalesce property accesses, guard missing keys, suppress side effects on empty state.","Avoid extending internal serializable classes (ArrayObject and friends) when you rely on constructor-less instantiation; wrap them instead of extending.","If the warning source cannot be fixed, instantiate that specific class via new or reflection yourself and keep it out of the instantiator's reach."],"exampleFix":"// before\nclass Snapshot\n{\n    public function __wakeup(): void\n    {\n        // notice on the empty synthetic payload during the probe:\n        // \"Undefined index: hydrated_at\" => fromUncleanUnSerialization()\n        $this->hydratedAt = $this->meta['hydrated_at'];\n    }\n}\n\n// after\nclass Snapshot\n{\n    public function __wakeup(): void\n    {\n        $this->hydratedAt = $this->meta['hydrated_at'] ?? null;\n    }\n}","handlingStrategy":"try-catch","validationCode":"$reflection = new ReflectionClass($className);\n\n// classes with internal ancestors go through the unserialize probe and may raise PHP warnings\n$hasInternalAncestors = false;\nfor ($r = $reflection; $r !== false; $r = $r->getParentClass()) {\n    if ($r->isInternal()) {\n        $hasInternalAncestors = true;\n        break;\n    }\n}\n\nif ($hasInternalAncestors && $reflection->isFinal()) {\n    // the synthetic unserialize payload may trigger warnings: instantiate explicitly instead\n    return $reflection->newInstanceWithoutConstructor();\n}\n\nreturn (new Instantiator())->instantiate($className);","typeGuard":"function emitsNoDiagnosticsDuringWakeup(string $className): bool\n{\n    $r = new ReflectionClass($className);\n\n    return ! $r->hasMethod('__wakeup')\n        && ! $r->hasMethod('__unserialize')\n        && ! $r->isSubclassOf(Serializable::class);\n}","tryCatchPattern":"use Doctrine\\Instantiator\\Exception\\UnexpectedValueException;\n\ntry {\n    $instance = $instantiator->instantiate($className);\n} catch (UnexpectedValueException $e) {\n    // message names the file/line of the PHP warning; getPrevious() holds the raw warning text\n    $warning = $e->getPrevious();\n    error_log(sprintf('Instantiator probe warning in %s: %s', $className, $warning?->getMessage()));\n\n    return new $className(...$constructorArgs);\n}","preventionTips":["Write __wakeup()/__unserialize() code that cannot raise notices on empty state: null-coalesce every property access.","Do not extend internal serializable classes (ArrayObject, ArrayIterator, SPL collections) if you rely on constructor-less instantiation — wrap them instead.","Run test suites with error_reporting(E_ALL) converted to exceptions so probe-hostile wakeup code fails during CI, not in production.","Check the chained previous exception for the exact warning text and code before assuming the instantiator is at fault."],"tags":["php","unserialization","php-warning","error-handler","wakeup"],"backgroundTag":"unserialize-raised-warning","analyzedSha":"cbb879d6eea7ce605d95f4c455679df73ee682ea","analyzedAt":"2026-08-21T03:06:19.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}