Yesterday our team faced problem saving system configuration in Magento 2 admin panel and they received the following exception “unable to unserialize value”.
1 exception(s): Exception #0 (InvalidArgumentException): Unable to unserialize value. Exception #0 (InvalidArgumentException): Unable to unserialize value.
After spending few hours our team came to know that this exception is related to \Magento\Framework\Serialize\Serializer\Json class. To be very specific the problem is in /vendor/magento/framework/Serialize/Serializer/Json.php file and there is a function unserialize($string) which gives you an exception if the string is already serialized.
The solution was to change the following file /vendor/magento/framework/Serialize/Serializer/Json.php especially the unserialize function.
Here is the original unserialize function -:
public function unserialize($string) { $result = json_decode($string, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \InvalidArgumentException('Unable to unserialize value.'); } return $result; }
Change the above function to the following -:
public function unserialize($string) { /* Added the following if clause to resolve the issue */ if($this->is_serialized($string)){ $string = $this->serialize($string); } $result = json_decode($string, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \InvalidArgumentException('Unable to unserialize value.'); } return $result; }
Also add the following is_serialized function in the same file /vendor/magento/framework/Serialize/Serializer/Json.php
function is_serialized($value, &$result = null) { // Bit of a give away this one if (!is_string($value)) { return false; } // Serialized false, return true. unserialize() returns false on an // invalid string or it could return false if the string is serialized // false, eliminate that possibility. if ($value === 'b:0;') { $result = false; return true; } $length = strlen($value); $end = ''; switch ($value[0]) { case 's': if ($value[$length - 2] !== '"') { return false; } case 'b': case 'i': case 'd': // This looks odd but it is quicker than isset()ing $end .= ';'; case 'a': case 'O': $end .= '}'; if ($value[1] !== ':') { return false; } switch ($value[2]) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: break; default: return false; } case 'N': $end .= ';'; if ($value[$length - 1] !== $end[0]) { return false; } break; default: return false; } if (($result = @unserialize($value)) === false) { $result = null; return false; } return true; }
Once the Json file was updated, we could manage to save the configuration without any issue. After saving the configuration we reverted the changes back to what it was and everything worked as expected there after.
Hope this article helped you in some way. Please leave us your comment and let us know what do you think? Thanks.
Thanks. It worked
Its not working in magento 2.2.6 for me
Please take review
Thanks
Hi Mns, Please make sure it is going in is_serialized function when you save from admin.
Thank you! It worked for magento 2.2.2
Thanks for leaving your comment. It will definitely help other users.
I have tried this solution but it’s not working for me. We are using Magento 2.2.6. Can I have any alternate solution for this issue?
It should work without any issue, alternatively you can find out which system configuration is using Magento\Config\Model\Config\Backend\Serialized\ArraySerialized as backend_model and update that configuration value directly in DB. Hope it helps.
I have this problem too, but when I change the json.php I get a 500 error…
Hi Niel, please check your system.xml and which field is using array serialised as backend_model. You can update core_config_data table directly in mySQL. Hope it helps!
Dont force magento to use serialization when it has been removed. Correct way to handle this is to convert your data properly.
https://magento.stackexchange.com/questions/196216/magento-2-2-error-unable-to-unserialize-value#answer-196946