{"record":{"id":"15e10feb02a34fca","repo":"phalcon/cphalcon","slug":"data-for-the-unserializer-must-be-of-type-string","errorCode":null,"errorMessage":"Data for the unserializer must be of type string","messagePattern":"Data for the unserializer must be of type string","errorType":"exception","errorClass":"Phalcon\\Storage\\Serializer\\Exceptions\\InvalidUnserializationInput","httpStatus":null,"severity":"error","filePath":"phalcon/Storage/Serializer/Base64.zep","lineNumber":41,"sourceCode":"     */\n    public function serialize() -> string\n    {\n        if typeof this->data !== \"string\" {\n            throw new InvalidSerializationInput();\n        }\n\n        return this->phpBase64Encode(this->data);\n    }\n\n    /**\n     * Unserializes data\n     */\n    public function unserialize(mixed data) -> void\n    {\n        var result;\n\n        if typeof data !== \"string\" {\n            throw new InvalidUnserializationInput();\n        }\n\n        let result = this->phpBase64Decode(data, true);\n\n        if unlikely false === result {\n            let this->isSuccess = false,\n                result          = \"\";\n        } else {\n            let this->isSuccess = true;\n        }\n\n        let this->data = result;\n    }\n}\n","sourceCodeStart":23,"sourceCodeEnd":56,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Storage/Serializer/Base64.zep#L23-L56","documentation":"Base64::unserialize(mixed data) requires the raw stored payload to be a string; any non-string input (int, float, bool, null, array, or the false a failed read returns) throws InvalidUnserializationInput before decoding starts. It is the decode-side twin of error 716.","triggerScenarios":"Storage backend returns a non-string raw value — another writer on the shared Redis/Memcached stored an unserialized scalar with SERIALIZER_NONE; manually calling unserialize() on data from cookies or external sources that is not actually base64 text; passing the result of a failed get() (false) back into the serializer.","commonSituations":"Shared cache between apps with different serializer settings; cache entries written by an older config or a different serializer; custom code paths that feed already-decoded values into unserialize().","solutions":["Guard the payload: if (!is_string($raw)) { /* treat as miss */ } before unserialize()","Make all writers to a shared backend use the same serializer and version","json_encode()/base64_encode() at the boundary so every stored value is a string","Clear stale entries when the serializer configuration changes (flush or version the prefix)"],"exampleFix":"// before\n$serializer->unserialize($raw); // $raw = 42 from a foreign writer -> throws\n\n// after\n$serializer->unserialize(is_string($raw) ? $raw : '');\n// or treat non-strings as a cache miss","handlingStrategy":"type-guard","validationCode":"if (!is_string($raw)) {\n    return $default; // treat non-string payloads as a cache miss\n}\n$serializer->unserialize($raw);","typeGuard":"function isBase64Payload(mixed $raw): bool\n{\n    return is_string($raw) && $raw !== '';\n}","tryCatchPattern":"try {\n    $serializer->unserialize($raw);\n} catch (\\Phalcon\\Storage\\Serializer\\Exceptions\\InvalidUnserializationInput $e) {\n    // foreign or corrupted entry — drop it and continue as a miss\n    $cache->delete($key);\n    return $default;\n}","preventionTips":["Keep serializer settings identical across every writer of a shared backend","Flush or version the cache prefix when changing serializers","Treat raw backend bytes as untrusted: type-check before decoding"],"tags":["php","phalcon","serialization","base64","cache","type-error"],"backgroundTag":"type-mismatch","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}