phalcon/cphalcon · error · Phalcon\Storage\Serializer\Exceptions\InvalidUnserializationInput
Data for the unserializer must be of type string
Error message
Data for the unserializer must be of type string
What it means
Php::unserialize() first applies isSerializable(): null, booleans and numeric values are returned as-is without decoding. Whatever remains must be a serialize() string; a non-string that survives the filter — array, object, resource — throws InvalidUnserializationInput. unserialize() is meant to consume serialize() output, not already-decoded data.
Source
Thrown at phalcon/Storage/Serializer/Php.zep:48
return this->phpSerialize(this->data);
}
/**
* Unserializes data
*/
public function unserialize(mixed data) -> void
{
var result;
if (true !== this->isSerializable(data)) {
let this->data = data;
return;
}
if unlikely typeof data != "string" {
throw new InvalidUnserializationInput();
}
globals_set("warning.enable", false);
set_error_handler(
function (number, message, file, line) {
globals_set("warning.enable", true);
},
E_NOTICE | E_WARNING
);
let result = this->phpUnserialize(data);
restore_error_handler();
if unlikely globals_get("warning.enable") || result === false {
let this->isSuccess = false,
result = "";
} else {View on GitHub (pinned to b7419de9cd)
Solutions
- Call unserialize() only with strings produced by serialize()
- Check before decoding: if (is_string($data)) { $serializer->unserialize($data); } else { $value = $data; }
- Rely on the adapter's get() — it serializes/unserializes exactly once per round-trip
- When accepting payloads from other systems, detect the format (leading 'a:1:{' vs '{') instead of assuming
Example fix
// before $serializer->unserialize($payload); // $payload already an array -> throws // after $value = is_string($payload) ? $serializer->unserialize($payload) && $serializer->getData() : $payload;
Defensive patterns
Strategy: type-guard
Validate before calling
if (is_string($payload)) {
$serializer->unserialize($payload);
$value = $serializer->getData();
} else {
$value = $payload; // already decoded
} Type guard
function isPhpSerializedString(mixed $data): bool
{
return is_string($data) && preg_match('/^[aObsiNd]:\d+:/i', $data) === 1;
} Prevention
- unserialize() only what serialize() produced — one decode per round-trip
- Prefer the adapter's get()/set() over manual serializer calls inside app code
- Detect payload format (serialize vs json) before decoding mixed-origin data
When it happens
Trigger: Passing an already-unserialized array to Php::unserialize() (double decoding); feeding an object/resource payload; storage returning an array-shaped payload into the serializer; queue/job code unserializing a message that was json-decoded earlier in the pipeline.
Common situations: Manual serializer use in job queues; mixing json_decode() and unserialize() pipelines; round-tripping a value through another serializer before this one; refactors that changed where decoding happens so it now runs twice.
Related errors
- Data for the serializer must be of type string
- Data for the unserializer must be of type string
- Invalid WHERE clause conditions
- Invalid bind parameter (1)
- Arguments must be an array or string, {type} given
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/9a2f6790e04e2b81.
Report an issue: GitHub.