{"record":{"id":"04f793e4f08d1aeb","repo":"guzzle/promises","slug":"should-never-be-serialized","errorCode":null,"errorMessage":" should never be serialized","messagePattern":" should never be serialized","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/NonSerializableTrait.php","lineNumber":14,"sourceCode":"<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * @internal\n */\ntrait NonSerializableTrait\n{\n    public function __serialize(): array\n    {\n        throw new \\LogicException(static::class.' should never be serialized');\n    }\n\n    public function __unserialize(array $data): void\n    {\n        throw new \\LogicException(static::class.' should never be unserialized');\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/guzzle/promises/blob/42118e66a53c492effaf92bc357e931985d5c6f9/src/NonSerializableTrait.php#L1-L22","documentation":"Classes using the internal NonSerializableTrait throw from __serialize() to block native PHP serialization. Promises and related objects hold live state (wait callbacks, closures, references to tasks/queues) that cannot survive serialize(), so the library fails fast instead of producing a broken, silently truncated object after unserialize(). static::class is interpolated into the message, naming the offending class.","triggerScenarios":"Calling serialize($obj), or triggering indirect serialization via $_SESSION, var_export-less caches, APCu/Redis stores, igbinary, job queues, or error logs that serialize context, on an object of a class using NonSerializableTrait (promises, EachPromise, etc.).","commonSituations":"Storing pending promises in a PHP session between requests; caching promise objects in Redis/Memcached; pushing promises onto queue payloads; serializing exception traces that embed promises.","solutions":["Do not serialize promise objects; store only plain data (the awaited value or rejection reason) and rebuild the promise after retrieval.","Call ->wait() to extract the concrete value before persisting, then wrap it in a new FulfilledPromise on the other side.","Exclude promise objects from serialized payloads (unset them or use a whitelisting serializer).","Log plain values, not promise instances."],"exampleFix":"// before\n$_SESSION['result'] = $promise; // serialize() later throws LogicException\n// after\n$_SESSION['result'] = $promise->wait(); // plain value\n$promise = new \\GuzzleHttp\\Promise\\FulfilledPromise($_SESSION['result']);","handlingStrategy":"try-catch","validationCode":"if ($stateful instanceof \\GuzzleHttp\\Promise\\PromiseInterface) {\n    throw new \\LogicException('Refusing to serialize a promise; persist ->wait() value instead.');\n}","typeGuard":"function assertSerializable($value): void\n{\n    if (is_object($value) && ($value instanceof \\GuzzleHttp\\Promise\\PromiseInterface)) {\n        throw new \\LogicException('Promises must not be serialized.');\n    }\n}","tryCatchPattern":"try {\n    $blob = serialize($obj);\n} catch (\\LogicException $e) {\n    $blob = serialize($obj->wait()); // persist the plain value instead\n}","preventionTips":["Never store promises in $_SESSION, caches, or queue payloads; store awaited values.","Sanitize payloads before serialize() to strip PromiseInterface instances.","When logging context variables, unwrap or redact promises first."],"tags":["serialization","promises","guzzle"],"backgroundTag":"object-not-serializable","analyzedSha":"42118e66a53c492effaf92bc357e931985d5c6f9","analyzedAt":"2026-09-14T00:10:14.865Z","contentChangedAt":"2026-09-14T00:10:14.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}