Improperly Serialized Variables in Database

When loading a page the following error occurs when loading an improperly serialized array from the variables table. The same technique can be used for bad serialized data in other tables.

Error

PHP Notice: unserialize() [<a href='function.unserialize'>function.unserialize</a>]: Error at offset 6 of 10 bytes in \includes\bootstrap.inc on line 428

Depending on how caching is set on your site, you may only see this error sometimes. Because once the variables are cached they may not be loaded every time.

Some Causes of Serialization Issues

  • Changing serialized content via sql replace command such as when migrating a site. You can't do this unless you follow up and put the
    length of the new value in by hand.
  • Serializing resources
  • Serializing objects and unserializing them without the class code loaded
  • Serialized string is truncated because it is too long for the field it is stored in.
  • Encoding/Decoding PHP/mysql issues
  • Incorrect installation/compilation/configuration of APC (php extension)

Debugging Technique

Around line 550 of bootstrap.inc in drupal 6 change the code to as follows. (Set aside the old code to replace afterward) This will show you the variables that are throwing errrors. The @ symbol before unserialize suppresses the error so all the variables can be checked before code execution stops.

 // if ($cached = cache_get('variables', 'cache')) {
 //   $variables = $cached->data;
 // }
 // else {
    $result = db_query('SELECT * FROM {variable}');
    while ($variable = db_fetch_object($result)) {
     
      $variables[$variable->name] = @unserialize($variable->value);
      
      if ($variables[$variable->name] === FALSE) {
       print "<hr/>Unserialize Error for variable:". $variable->name . '='. $variables[$variable->name] . "<br/>". $variable->value;
      }
    }
    die;
    cache_set('variables', $variables);
 // }
 

You may only get the error when variables are first loaded. After that they may be cached. So to reproduce the error, flush the cache via sql:

truncate table cache_block;
truncate table cache;
truncate table cache_content;
truncate table cache_filter;
truncate table cache_form;
truncate table cache_menu;
truncate table cache_views;

Resolution

If you are getting errors with all or many of your variables, this technique will not work as the cause is likely not isolated bad record(s) in your variables table.

Once you find the bad variable(s), you will need to fix it in the database. (You may also override the variable by setting its value in the $conf array as described at the bottom of the settings.php file but you will not be able to change the variable value via the web interface until you remove the override in settings.php)

Below are what serialized arrays should look like. (look in the variables table):

name: node_options_bio
value: a:1:{i:0;s:6:"status";}

name: googleanalytics_track_6
value: b:0;

The i represent integers, s strings, and the count is the length within the quotes.

You may be able to fix the value by hand editing it the database table. If you can't, you may just want to delete it, saving the old value somewhere, and let Drupal set it to its default. This may cause problems for some variables.

How you can remove the above error.

// Added by Deb
-- Open includes/bootstrap.inc file drupal 6.22
-- Go to line no 568
-- Paste below code after the line no 568 or "$variables[$variable->name] = unserialize($variable->value);" line.
  if ($variables[$variable->name] === FALSE) {    
      variable_set($variable->name, ""); //here all the blank variable will be true
  }
-- After changing all the necessary variable in database (variable table), please delete the edited code and clear the cache and truncate the watchdog table and refresh the page again.
--Check in admin "recent log entries"

APC related issues

Incorrect installation, configuration or compiling of the php extension APC from the PECL repository can also produce similar unserialize errors. If you have the APC extension enabled, try disabling it in your php.ini (look for extension=apc.so) and then restarting your web-server.

If disabling APC fixes the issue then it is likely that it has not been installed correctly or that the extension is incorrectly configured. Please consult the php manual for the correct way to install the extension for your particular server.

Red-hat based servers (Fedora, RHEL, Centos) can use yum to install the package php-pecl-apc instead of using pecl install apc. Using yum to install the extension instead of building it with PECL seems to fix the unserialize issues in some instances on these distributions.

Comments

torvall’s picture

To find which variables are not serialized correctly, I created a block with this code, using the PHP input format:

$result = db_query('SELECT * FROM {variable}');
    while ($variable = db_fetch_object($result)) {
    
      $variables[$variable->name] = @unserialize($variable->value);
     
      if ($variables[$variable->name] === FALSE) {
       print "<hr/>Unserialize Error for variable:". $variable->name . '='. $variables[$variable->name] . "<br/>". $variable->value;
      }
    }

It's much more practical (and safe) than messing up with Drupal core files.

TwoD’s picture

If, which is very likely, you've got variables storing just a serialized version of the boolean FALSE ("b:0;"), the above code will consider it an error.
I suggest modifying it slightly to ignore that case:

$serialized_false = serialize(FALSE);
$result = db_query('SELECT * FROM {variable}');
    while ($variable = db_fetch_object($result)) {
      $variables[$variable->name] = @unserialize($variable->value);
      if ($variables[$variable->name] === FALSE && $variable->value !== $serialized_false) {
       print "<hr/>Unserialize Error for variable:". $variable->name . '='. $variables[$variable->name] . "<br/>". $variable->value;
      }
    }
gbell12’s picture

I don't like the above methods of debugging because you don't want to suppress the unserialize error output.

I like to use this bit of PHP:

#!/usr/bin/php

<?php
$conn = new MySQLi('localhost', 'root', '', 'drupal_gypsy');

if (!$conn) {
  die("MySQL error: #{$conn->connect_errno}: {$conn->connect_error}");
}

$result = $conn->query("select * from gypsy_variable");

while ($row = $result->fetch_row()) {
  print $row[0];
  $data = unserialize($row[1]);
  print "    ";
  print $data . "\n";
  print "-------------------\n";
}

It shows I have one corrupted row whose data is this:

a:27:{s:17:"zen_block_editing";i:0;s:14:"zen_breadcrumb";s:2:"no";s:24:"zen_breadcrumb_separator";s:5:" › ";s:19:"zen_breadcrumb_home";i:1;s:23:"zen_breadcrumb_trailing";i:1;s:20:"zen_breadcrumb_title";i:0;s:20:"zen_rebuild_registry";i:0;s:14:"zen_wireframes";i:0;s:11:"toggle_logo";i:1;s:11:"toggle_name";i:1;s:13:"toggle_slogan";i:0;s:14:"toggle_mission";i:0;s:24:"toggle_node_user_picture";i:0;s:27:"toggle_comment_user_picture";i:0;s:13:"toggle_search";i:0;s:14:"toggle_favicon";i:1;s:20:"toggle_primary_links";i:1;s:22:"toggle_secondary_links";i:0;s:12:"default_logo";i:0;s:9:"logo_path";s:43:"sites/gypsyfalls/files/hg_template_logo.png";s:11:"logo_upload";s:0:"";s:15:"default_favicon";i:0;s:12:"favicon_path";s:41:"sites/gypsyfalls/themes/gypsy/favicon.ico";s:14:"favicon_upload";s:0:"";s:14:"default_banner";i:0;s:11:"banner_path";s:0:"";s:13:"banner_upload";s:0:"";}

Good lord! Where's the problem? Well, the error from unserialize says:

Notice: unserialize(): Error at offset 108 of 876 bytes in /data/www/gypsyfalls/
find_bad_var.php on line 14

Using this and "cut" under Linux, I can at least get the context:

$ cut --bytes=104-112 bs2
 › ";s:

Text search for that and I see it's this guy:

s:5:" › "

That's an s:3 not an s:5!!

VERY DISTURBING that there's a PHP or Drupal bug that's corrupting my variables table! Anybody know of an existing ticket somewhere I can pile onto?

debrajn’s picture

Thanks Johnbarclay, xtfer, larowlan and tobiasb
This code is very much helpful for me. I have added extra piece of info please see section
How you can remove the above error

Regards,
Deb

Nikdhil Mdohfan’s picture

Do not alter values manually
You can use Online Sterilizer test serialize online

Thanks.

pmannle’s picture

Thanks all, I was able to identify and fix a unserialize() error I was faced with.

I used the code posted by @gbell12 by putting it into a self-contained php file in my docroot. Also, make sure you are selecting from the variables table from your drupal database.

In the code, make sure to enter your password here:

$conn = new MySQLi('localhost', 'your_user', 'your_password', 'your_drupal_database');

Then, view the source of the output from your new php file, and you will see the serialize error right underneath the data row that has the data that needs to be fixed. In my case, it was an email address that I had replaced by manually editing the sql files (not a great idea unless you have to), and the new email address was shorter than the original one, so the s: value was wrong - therefore the error.

purna_dey’s picture

Thanks a lot. johnbarclay!

// Added by Deb
-- Open includes/bootstrap.inc file drupal 6.22
-- Go to line no 568
-- Paste below code after the line no 568 or "$variables[$variable->name] = unserialize($variable->value);" line.
if ($variables[$variable->name] === FALSE) {
variable_set($variable->name, ""); //here all the blank variable will be true
}
-- After changing all the necessary variable in database (variable table), please delete the edited code and clear the cache and truncate the watchdog table and refresh the page again.
--Check in admin "recent log entries"

dkane’s picture

Thank you everyone for your solutions and clear explanations in this post. Using what I learned here I came up with a quick and painless fix that worked for me.

Setup: I had to migrate my site to a new server, and when I did I got many serialized variable errors. Here is how I resolved the problem (D6):

(PLEASE NOTE: I highly recommend backing up your database before making any manual corrections to entries, or at least copy the contents of the problem entries to a text editor for safe keeping until you know you've done a good thing).

Step 1: Download and instal the Variable Check module (http://drupal.org/project/variablecheck)

Step 2: Check the module's report page to see what is returning errors (admin/reports/variablecheck)

Step 3: Login to PHPmyAdmin and do a database wide search for the name of the variable returning the error and choose to edit it

Step 4: Copy the value of the field.

Step 5: Open the "Serialize and Unserialize web tool" in a separate window (http://unserialize.net/serialize)

Step 6: Select to translate from "PHP Serialize" to "PHP Serialize"

Step 7: Paste the bad entry in the first text box and click the "Process" button and Voila! your serialized entry has been repaired!

Step 8: Copy the new entry back into your database and save the record. Lather. Rinse. Repeat.

McJax’s picture

Thanks for this dkane, very straightforward and fixed my issues quickly.

fehin’s picture

Beware, http://unserialize.net/serialize redirects to adult sites

adolf.mrls’s picture

http://unserialize.net/serialize
not exits ... :(

please help,
where i my fix Unserialize data???
or how i can fix :
i:0
i:1
b:0
b:1

Chris McGrath’s picture

https://drupal.org/project/variablecheck

This worked for me on a D6 site. Identified variables, then used Devel variable editor to delete those that were unserialized.

Seem to have come from a module that was removed improperly and left remnants in the DB.

jessZ’s picture

after an upgrade and using hand edits to kill 25 or so duplicate filenames and filepaths that were blocking the dbase upgrade from 6-7 and truncating a few fields that were throwing errors in migrating fields in cck, I am getting lots of instance this error in a drupal 7 version of the site. I have a list of all the entries i deleted or altered but not sure where to look for the "serialize" variable. How serious is this error? I can completely delete the relevant nodes if necessary but not sure that's really a way to go. I also had to delete a number of D5.x modules to get from 5 to 6 and (this dbase /website was born in 4.7 about 10 years ago and has 4000 or so nodes of content and about 2000 images.

There is now a drupal 7 module that will tell you where the errors are coming from:
https://www.drupal.org/project/variablecheck After installing run a status report and it will allow you to see what variables are corrupted.

I haven't gotten rid of the error yet but it doesn't appear to be from the suspected source (deletions) but from old 5.x custom themes. I am investigating further. After deleting the variables generated from that source (and removing the old themes from the sites/all/themes directory the same error class (not the same line numbers( is still showing up in numerous places.

After running the variable check I get a new error that the dbase needs updating but attempting the update yields: "Some of the pending updates cannot be applied because their dependencies were not met."

After numerous fatal errors trying to unistall using the actual module uninstall feature i simply took the offending modules out of the directory. Seems to have reduced the number of errors being thrown. I think if i now disable and reinstall a couple of these phantom modules date migration/ and cck related i might get a clean error log. At least the site is working in 7. A loooong process to get from 5.x to 7. (If drupal continues to be this kludgy with migration and upgrade i may just throw in the towel and migrate to Wordpress (aaaargh please no!)

anthonyf’s picture

I got 3 variable table "unserialize" errors from bootstrap.inc after migrating a production site down to my Mac. I wanted to get rid of these notices on my local dev site so they wouldn't distract me from other messages during module development. I used the Variable Check module as has been suggested here, and it revealed three variable rows with issues:

maintenance_mode_message
site_mail
webform_default_from_address

I found I could fix these without doing any direct deletes against the variables table.

Using the Admin interface, I went to the Configuration->Maintenance Mode page and saw that there was no maintenance mode message. I added a message, saved, cleared cache, and one notice went away. I did the same for the other two: site_mail was the email address in Configuration->Site Information, and webform_default_from_address was the email "from address" in Configuration->Webform Settings. In both of these cases, the value was missing and adding a new value, saving, and clearing the cache fixed the problem.

MykolaVeryha’s picture

$databases = array (
  'default' =>
    array (
      'default' =>
        array (
          'driver' => 'mysql',
          'database' => 'martin',
          'username' => 'root',
          'password' => '1111',
          'host' => 'localhost',
          'port' => '',
          'prefix' => 'dp614_',
<strong>          'charset' => 'utf8mb4',
          'collation' => 'utf8mb4_general_ci',</strong>
        ),
    ),
);