Hi,

I just recently upgraded a site from D6 and I'm getting the following set of errors for each product with attribute options on a view displaying a mix of both products with attributes and products without:

Warning: Illegal string offset 'attributes' in _uc_attribute_alter_form() (line 1293 of /opt/html/drupal7/sites/all/modules/ubercart/uc_attribute/uc_attribute.module).

Notice: Array to string conversion in _uc_attribute_alter_form() (line 1293 of /opt/html/drupal7/sites/all/modules/ubercart/uc_attribute/uc_attribute.module).

Notice: unserialize(): Error at offset 0 of 72 bytes in _uc_product_get_variant() (line 646 of /opt/html/drupal7/sites/all/modules/ubercart/uc_product/uc_product.module).

I ran through all of the correct upgrade procedures and ran update scripts etc during the upgrade. At the moment I'm running UC 3.5.

I've been looking for each individual error all morning but can't seem to find anyone with a similar issue (of all three). From what I've been reading the offset error generally means corrupt database entries. I've had a look through and there's no missing or seemingly corrupt entries in options or attributes in the DB. (http://www.ubercart.org/forum/bug_reports/34088/notice_unserialize_funct...)

The products still show correctly with their options (selectable) on the view (despite the errors) and the errors don't show on the product nodes, only the View.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

TR’s picture

Issue tags: -6x upgrade to 7x

Did you upgrade to the latest version of Ubercart 2 before you upgraded to Drupal 7 / Ubercart 3?

GuyRus’s picture

Issue tags: +6x upgrade to 7x

Yep, ran through the upgrade procedure as per the Drupal Documentation. It's quite a large site and this is the only error I've got so don't believe it's due to a flaw in the upgrade process.

GuyRus’s picture

Just to update this, I found this thread: https://drupal.org/node/1114304#comment-4402598 and removed two rows 'uc_quote_enabled' and 'uc_quote_method_weight' and still have the unserialize error. The only result left on the query

SELECT name, LENGTH( value ) , value
FROM variable
WHERE LENGTH( value ) = 72

is a variable called 'drupal_private_key' - which I'm hesitant to remove as it's not relating to UC and could have larger implications (from what I've read of it: https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_... )

Any help is greatly appreciated!

TR’s picture

Issue tags: -6x upgrade to 7x

Please read the tag guidelines: https://drupal.org/node/1023102

You're interpreting https://drupal.org/node/1114304#comment-4402598 wrong - that doesn't seem to have anything to do with your problem. Specifically, that talks about an error unserializing the variable table. That's not what's generating your error here. PHP serialization is used all over the place in Drupal, and in this case line 646 of uc_product.module doesn't have anything to do with system variables. Those two rows you removed from the variable table shouldn't hurt anything, you'll just have to go through your shipping quotes settings again and make sure it's configured the way you want. But don't remove any other rows, especially drupal_private_key ...

GuyRus’s picture

My bad on the tags. Thanks for your reply!

Shipping quotes are fine, I can reconfig that easily.

A little further info: The errors only come up when the products are being output via a view (the product node itself is fine) and only when the 'add to cart form' is in the view. Errors show for both page view and block view under these conditions.

There are no relationships in the view.

The other thing which was a little strange is when editing the view there were no errors in the view preview.

TR’s picture

Status: Active » Postponed (maintainer needs more info)

Maybe you could export your View and post it here so we could try to reproduce the error - it's unclear to me why you say it's an upgrade error, perhaps that View also shows the error on a fresh install of D7 and it has nothing to do at all with the upgrade?

longwave’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)

No further info provided.

TR’s picture

haysuess’s picture

Re-opening per the request of TR.

I get the same errors on a fresh Drupal 7 install. I have the Add to Cart form and a few other items in a block that is shown on the proper product nodes via Contextual Filters.

If the attributes are required, no errors. If the attributes are NOT required, then I get errors.

Here is my view, including (probably) extraneous stuff:

$view = new view();
$view->name = 'add_to_cart';
$view->description = 'Add to Cart block to show in the sidebar of product pages';
$view->tag = 'default';
$view->base_table = 'node';
$view->human_name = 'Add to Cart';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['style_plugin'] = 'default';
$handler->display->display_options['row_plugin'] = 'fields';
/* Field: Product: Display price */
$handler->display->display_options['fields']['display_price']['id'] = 'display_price';
$handler->display->display_options['fields']['display_price']['table'] = 'uc_products';
$handler->display->display_options['fields']['display_price']['field'] = 'display_price';
$handler->display->display_options['fields']['display_price']['label'] = '';
$handler->display->display_options['fields']['display_price']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['display_price']['element_default_classes'] = FALSE;
/* Field: Product: Add to cart form */
$handler->display->display_options['fields']['addtocartlink']['id'] = 'addtocartlink';
$handler->display->display_options['fields']['addtocartlink']['table'] = 'uc_products';
$handler->display->display_options['fields']['addtocartlink']['field'] = 'addtocartlink';
$handler->display->display_options['fields']['addtocartlink']['label'] = '';
$handler->display->display_options['fields']['addtocartlink']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['addtocartlink']['element_default_classes'] = FALSE;
$handler->display->display_options['fields']['addtocartlink']['hide_alter_empty'] = FALSE;
/* Field: Global: Custom text */
$handler->display->display_options['fields']['nothing']['id'] = 'nothing';
$handler->display->display_options['fields']['nothing']['table'] = 'views';
$handler->display->display_options['fields']['nothing']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing']['label'] = '';
$handler->display->display_options['fields']['nothing']['alter']['text'] = 'Or <a href="/panopass">download this item FREE</a> with a PanoPass';
$handler->display->display_options['fields']['nothing']['element_label_colon'] = FALSE;
/* Field: Content: Features */
$handler->display->display_options['fields']['field_features']['id'] = 'field_features';
$handler->display->display_options['fields']['field_features']['table'] = 'field_data_field_features';
$handler->display->display_options['fields']['field_features']['field'] = 'field_features';
$handler->display->display_options['fields']['field_features']['label'] = '';
$handler->display->display_options['fields']['field_features']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['field_features']['type'] = 'textformatter_list';
$handler->display->display_options['fields']['field_features']['settings'] = array(
  'textformatter_type' => 'ul',
  'textformatter_comma_and' => 0,
  'textformatter_comma_full_stop' => 0,
  'textformatter_comma_override' => 0,
  'textformatter_separator_custom' => '',
  'textformatter_separator_custom_tag' => 'span',
  'textformatter_separator_custom_class' => 'textformatter-separator',
  'textformatter_comma_tag' => 'div',
  'textformatter_class' => 'features-list',
);
/* Field: Content: Tags */
$handler->display->display_options['fields']['field_tags']['id'] = 'field_tags';
$handler->display->display_options['fields']['field_tags']['table'] = 'field_data_field_tags';
$handler->display->display_options['fields']['field_tags']['field'] = 'field_tags';
$handler->display->display_options['fields']['field_tags']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['field_tags']['delta_offset'] = '0';
$handler->display->display_options['fields']['field_tags']['multi_type'] = 'ul';
/* Contextual filter: Content: Nid */
$handler->display->display_options['arguments']['nid']['id'] = 'nid';
$handler->display->display_options['arguments']['nid']['table'] = 'node';
$handler->display->display_options['arguments']['nid']['field'] = 'nid';
$handler->display->display_options['arguments']['nid']['default_action'] = 'default';
$handler->display->display_options['arguments']['nid']['default_argument_type'] = 'node';
$handler->display->display_options['arguments']['nid']['summary']['number_of_records'] = '0';
$handler->display->display_options['arguments']['nid']['summary']['format'] = 'default_summary';
$handler->display->display_options['arguments']['nid']['summary_options']['items_per_page'] = '25';
$handler->display->display_options['arguments']['nid']['validate']['type'] = 'node';
/* Filter criterion: Content: Published */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'node';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = 1;
$handler->display->display_options['filters']['status']['group'] = 1;
$handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;

/* Display: Add to Cart Block */
$handler = $view->new_display('block', 'Add to Cart Block', 'block_1');
TR’s picture

Status: Closed (cannot reproduce) » Active
TR’s picture

Title: Upgrade from D6 errors » Warnings and Notices when using Add to Cart form in a View
Version: 7.x-3.5 » 7.x-3.x-dev

Better title.

haysuess’s picture

Any ideas yet? This is the only thing holding back the launch of a new site :-/

I'd like to make the attributes non-required to eliminate the extra steps for the end users.

haysuess’s picture

I really need help on this and have read all the info I can find regarding these errors about 10 times, but have no clue what the do next, besides hiding warnings and notices and hoping everything is OK.

Can anyone point me in the right direction?

haysuess’s picture

The only way I can get the errors to disappear is to delete line 1380 of uc_attribute.module, which is:

$attribute->default_option = NULL;

This works for me because although the attributes are still required, the default option is now automatically selected instead of it saying "- Select -" with no default. 99% of my buyers will buy the default option, so this works great for me, even though it's a hack.

I'll gladly "unhack" it if someone can figure out why I'm getting the errors above.

zippyguppy’s picture

I'm not sure whether this belongs in this thread or a new one.

I'm getting the same 3 errors:

Warning: Illegal string offset 'attributes' in _uc_attribute_alter_form() (line 1293 of /home3/lyla/public_html/order/sites/all/modules/ubercart/uc_attribute/uc_attribute.module).

Notice: unserialize(): Error at offset 0 of 42 bytes in _uc_product_get_variant() (line 614 of /home3/lyla/public_html/order/sites/all/modules/ubercart/uc_product/uc_product.module).

Notice: Array to string conversion in _uc_attribute_alter_form() (line 1293 of /home3/lyla/public_html/order/sites/all/modules/ubercart/uc_attribute/uc_attribute.module).

In my case I'm getting these when I try to create a new product with options. The options that I'm selecting aren't saving, and I'm ending up with a blank text box on the product page. The options used to work fine, and I can't figure out what's changed or how to fix it, but we really need options to work on this site.

Thanks in advance for the help!

zippyguppy’s picture

No, wait, looking through the logs I think I'm getting those 3 errors ALL the time.

And also - and I'm assuming the problems are related - I'm unable to make the options work properly.

longwave’s picture

Do you have any extra Ubercart related modules installed?

zippyguppy’s picture

I haven't added anything new, but these are all installed:
- cart links (which we don't actually use- I should disable that)
- product power tools
- ajax administration
- product checkout panes
- register invoice templates
- webform checkout pane

zippyguppy’s picture

I've flushed caches, run cron, checked the integrity of the database. Everything seems fine, but the errors are continuing. Argh!

Morbus Iff’s picture

I'm getting this too, but only only certain products. As reported by others:

  • I am using a View to add the "Add to cart" form on a page.
  • On the page, 2 of the products, out of 25 or so, are generating the warnings.
  • There are three warnings generated per product (so, in my case, a total of 6).
  • These warnings don't appear to impact the site's functionality at all.

The warnings are:

  • Warning: Illegal string offset 'attributes' in _uc_attribute_alter_form() (line 1293 of uc_attribute.module)
  • Notice: Array to string conversion in _uc_attribute_alter_form() (line 1293 uc_attribute.module).
  • Notice: unserialize(): Error at offset 0 of 24 bytes in _uc_product_get_variant() (line 614 of uc_product.module).

Focussing in on the first warning, the lines around 1293 are:

    if (!empty($values)) {
      $data = $product->data;
      $data['attributes'] = $values;
      if (isset($product->qty)) {

If I print out $data, I'll see the following on the page:

'A:1:{s:7:"contact";i:1;}'
array (
  'contact' => 1,
  'module' => 'uc_product',
  'attributes' => 
  array (
    1 => '3',
  ),
)

That is - the function appears to be running twice, and the first time $product->data is used, it's a serialized string, which causes the warnings. The second time the function is used, it's turned into an array, and the warnings appear to go away.

Bizarrely, I have no idea what that "contact" key is, in the serialized string. I've grepped both the UC source, all the UC modules I use, and all the custom modules I use, and I can't find anything that adds "contact" to the product data. Nor does re-saving the product, or the product's attributes, make it go away.

longwave’s picture

As products are just nodes, it could be some other contrib module that affects nodes in some way? Do you have any non-UC contrib modules that contain the string "contact"?

I guess 'data' is a bad choice of key when nodes are not really specific to Ubercart.

Morbus Iff’s picture

Nothing with a narrow grep:

/sites/all/modules > grep -R contact * | grep data
contrib/ctools/page_manager/plugins/tasks/contact_user.inc:  return _contact_personal_tab_access($context->data);
contrib/ctools/plugins/content_types/contact/user_contact.inc:  if (!_contact_personal_tab_access($context->data)) {
contrib/ctools/plugins/content_types/contact/user_contact.inc:  $block->content = drupal_get_form('contact_personal_form', $context->data);
contrib/views/modules/contact/views_handler_field_contact_link.inc:    if (!$menu_item['access'] || empty($account->data['contact'])) {
contrib/views/modules/contact.views.inc: * Provide views data and handlers for contact.module.
contrib/views/modules/contact.views.inc:function contact_views_data_alter(&$data) {
contrib/views/modules/contact.views.inc:  $data['users']['contact'] = array(
/public_html/modules > grep -R contact * | grep data
contact/contact.admin.inc:  // Get all the contact categories from the database.
contact/contact.module:  if (empty($account->data['contact'])) {
contact/contact.module: *   An array with the contact category's data.
contact/contact.module:      '#default_value' => !empty($account->data['contact']) ? $account->data['contact'] : FALSE,
contact/contact.module:  $edit['data']['contact'] = isset($edit['contact']) ? $edit['contact'] : variable_get('contact_default_status', 1);
longwave’s picture

Status: Active » Postponed (maintainer needs more info)

Strange. Must be coming from somewhere, but none of the above seem to be likely candidates. Unable to reproduce this myself, I'm afraid.

Morbus Iff’s picture

At the very least, one could do an is_array() check against $product->data...

longwave’s picture

Patches welcome, as is confirmation that the same fix works for the other people that are experiencing this issue.

Morbus Iff’s picture

(I'll unlikely patch this, as I'd rather find out what dastardly deed is adding 'contact', why it's being called twice, and when unserialization is happening.)

ñull’s picture

putting a dpm($data), I can see that $data not always is the expected array, but the serialized string of the array. So may be the source of this $product->data is where the bug needs to be fixed, because its output is inconsistent. It either should be always serialized or unserialized, not both.

Until you find out what writes this data, you can hack it this way:

      $data = is_array($data)?$data:unserialize($data);
      $data['attributes'] = $values;

This it least guarantee that data is unserialized when necessary.

ñull’s picture

Looks like I found out where it gets unserialized. It's in function _uc_product_get_variant($node, $data = FALSE) which is turn is called by function uc_product_load_variant($nid, $data = FALSE) and both are in uc_product.module.

A comment in _uc_product_get_variant also tells me why there is an extra occurance with serialzed data:

// Ensure that $node->data is an array (user module leaves it serialized).

So the serialized data must be because it is called by the user module. To avoid that serialized data is interpreted as unserialized array we have to always load the product with uc_product_load_variant before anything is done with $product->data. That is the only correct way to load a variant.

I now hacked again more correctly and inserted a $product=uc_product_load_variant($product->nid); before $product->data is ever used and now it works correctly without warning. Will now try to produce proper patch for this.

haysuess’s picture

Looking forward to this so I can "un-hack" what I did in #14.

ñull’s picture

ñull’s picture

Category: Support request » Bug report
Status: Postponed (maintainer needs more info) » Needs review
TR’s picture

@ñull: So apparently some other module is corrupting $product->data, and your patch works by reloading $product->data (which, incidentally, will destroy what that other module did, causing that other module to malfunction...). While that hides the problem from Ubercart's point of view, I don't think it solves the underlying issue that another module shouldn't be adding arbitrary data members like "data" to the product content type. Or if it does add to data[] (for example, an Ubercart extension might want to do this), then it should do so with an array_merge() rather than by totally overwriting data[].

So what is this other module that's overwriting the product's data array with the 'contact' array? It seems that's where the problem should be fixed.

Morbus Iff’s picture

@TR: Per null's comment, and the Ubercart source code:

http://api.drupalize.me/api/drupal/function/_uc_product_get_variant/7

It appears to be user.module, which also explains the "contact" key I'm seeing (coming from contact.module, which operates on user objects). Why, however, user.module is interfering with a $node, I have no idea (perhaps something upstream is merging user and node into one object?)

longwave’s picture

Status: Needs review » Needs work

I agree with TR; this fix is just covering up the real problem, we should figure out why $product->data is getting corrupted to start with, and why user.module appears to be involved when this should be purely related to nodes.

Does anyone have steps to reproduce this from a clean install? I guess I would at least need contact.module, which I never use personally.

haysuess’s picture

I get the same errors and do NOT have the Contact module enabled. I've done as much debugging as I know how to do and listed all the information I have above.

ellastelter’s picture

I am having the same issue... subscribing.

ñull’s picture

Status: Needs work » Needs review

The implementation of the user module's node_load hook is doing this. So every time a node_load takes place, the serialized data of the user is copied to the node data. This is not a bug, but apparently belongs to core. In stead of fixing core, UC developers made the function I used in my patch, to work around this quirk in D7.

The previously quoted code comment is essentially saying it. My interpretation: Since core (user.module) is doing it this way, we have to make sure it is unserialized for our purposes. I followed that reasoning and put the appropriate function to take care of that.

In D8 this hook implementation does not even exist, so in UC4 this work around is not needed any more.

ñull’s picture

Is there still anybody in disagreement with me? When not, I would like to see my patch promoted to "Reviewed and Tested" so that this can end up at least in a dev version.

bellagio’s picture

after applying the patch, errors are gone but price doesn't change anymore when attribute (+$10.00) changes..

bellagio’s picture

Step to reproduce: clean install with basic modules installed. right now i only have one product and one article page. I am trying to show child products list (UC product) under specific article node which describes common specs of the child products.

1. add entity reference field in product node to reference article content type.
2. Create views block with Contextual filter-(Content entity referenced from field_entity_reference_to_master) Content: Nid.
3. Article page throws errors with views block (child product) at the bottom when attribute is NOT required.

I tried with UC 7.x-3.x-dev and the error shows when attribute is not required.

philsward’s picture

I'm not sure it's views specific... I'm receiving a similar error with the Add to Cart form in Panels.

Location	https://www.mywebsite.com/uc_ajax_cart/add/item
Referrer	https://www.mywebsite.com/products/small-widget
Message	Notice: unserialize(): Error at offset 0 of 53 bytes in _uc_product_get_variant() (line 614 of /home/user/public_html/sites/all/modules/contrib/ubercart/uc_product/uc_product.module).

From what I can tell, it isn't causing me any issues other than the watchdog error, however each product with the error has a different offset.

I have the conditional attributes, ajax cart and the discount modules enabled.

Might be related, might be a separate issue. Just thought I'd share my findings.

sch2’s picture

I tried the patch provided in #30 and, while it make the errors go away, it also caused the price to not change anymore when attribute option changed.

I get these errors only when the attribute is not required.

TR’s picture

Status: Needs review » Needs work

#39, #40, and #42 all report the same problem with the patch. Moving to "Needs work".

strings6’s picture

I've got a view content pane in panels overriding the taxonomy term page for my Product Category vocabulary, and I get the same error on term pages that have products with attributes. There is no error on the actual product detail page, but only on the product list page prior to that.

I also fall into the scenario of a D6 -> D7 upgrade.

The error points to this line:
$data['attributes'] = $values;

The error is:
Warning: Illegal string offset 'attributes' in _uc_attribute_alter_form() (line 1293 of... .../sites/all/modules/ubercart/uc_attribute/uc_attribute.module).

Has anyone figured out the cause or fix?

strings6’s picture

I'm still wondering if anyone has any new insight on this error related to uc_attributes, where products that have attributes, and are displayed in a view block or view content pane in a panel, show an error.

We found that identical code works perfectly on an older version of Debian (Squeeze), but it errors when on a newer version of Debian (Wheezy). Could this error simply be caused by later versions of php, and thus needs a coding tweak to be made current?

strings6’s picture

In sites/all/modules/ubercart/uc_attribute/uc_attribute.module, line 1292, there a line of code that says:

$data = $product->data;

The error I was getting was from the the next line down, line 1293:

$data['attributes'] = $values;

It seems it did not like trying to assign an array (which $values is) to $data['attributes'] when $data was holding a serialized array.

For me, the fix was to unserialize() the right side first at line 1292, like this:

$data = unserialize($product->data);

After doing that, line 1293 no longer threw up errors.

Is it possible that older versions of php automatically unserialize a serialized array in some cases, whereas newer versions would not?

Thoughts?

strings6’s picture

It would seem that sometimes the $product->data is already an array. I had to add a check to see if it was a string before unserializing it:

if(is_string($product->data)) {
  $data = unserialize($product->data);
}
else {
  $data = $product->data;
}
julia_g’s picture

I had the same error after updating to the new PHP version, and #47 works for me, thanks strings6 !

bellagio’s picture

#47 works for me too, no more errors. thank you strings6!!

DaveH1234’s picture

Confirm that #47 is working for me. This error appeared from a PHP upgrade 5.3 to 5.5.
Suggest creating a patch and rolling into dev.

rfay’s picture

Component: Products » Product attributes
Status: Needs work » Needs review
FileSize
1.07 KB

It turns out that although $node->data aka $product->data is used widely here, it's actually *populated* initially by the user module, in user_node_load(), with the node author's userdata, in serialized string form. So basically all attempts to use $node->data as an array will fail until it gets somehow overwritten as an array by various means.

I haven't attempted to fix any of the assumptions about $product->data, but this simple patch moves the test to see if $product->data is an array to *before* it gets used as an array.

Since $product->data is really something introduced by user_node_load(), and is intended to represent user data, it would probably be a good move to refactor all uses of $node->data for *Ubercart* to $node->uc_data or something like that. There is no reason I can see to piggyback on the $node->data. This isn't saved anyway, it just gets built up as the node is processed by all of its friends.

longwave’s picture

The problem with refactoring this now is there may be contrib or custom code that relies on Ubercart's interpretation of $node->data (the same reason it cannot be removed from core, even though it seems pretty useless to provide only the serialized string).

The fix in #51 seems like a reasonable solution at this stage. It would be good to get a positive test result from someone else who is seeing this problem.

Morbus Iff’s picture

Status: Needs review » Reviewed & tested by the community

#51 worked for me.

rakun’s picture

#51 solves the problem for me to.

deja711’s picture

Just tested and works for me as well.

Arunah’s picture

#51 works like a charm, thx

  • longwave committed 6c6743d on authored by rfay
    Issue #2041977 by rfay: Warnings and Notices when using Add to Cart form...
longwave’s picture

Status: Reviewed & tested by the community » Fixed

Committed #51.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.