Description
If a discount has been applied to an order the "My Shipping information is the same as my Billing information" fails to work, the AJAX call returns a 500 server error.
The problem appears to be triggered by the validation function commerce_customer_profile_copy_validate()
which does quite a bit of refreshing and saving of the order object. This calls the commerce_discount module's commerce_discount_commerce_cart_order_refresh()
function, which deletes and re-creates discount lines. A little later in the AJAX callback code the original order is used, but this refers to the now-deleted discount line item, and so it fails with EntityMetadataWrapperException: Unable to get the data property commerce_unit_price as the parent data structure is not set
.
Original Description, for posterity
I have an occasional random failure for the Shipping Address to appear, when the "My Shipping information is the same as my Billing information" checkbox is deselected.
Has been noticed on Apple Mac with Safari, and Windows 8.1 with Firefox. So it doesn't seem to be an OS or browser-specific problem.
Typically when I ask the user for more details, they report that the function is now working for them.
I've tried, and failed, to reproduce the problem on my machine with all the browsers I have.
When I asked about the rotating arrows, one user reported that they didn't see those: they deselected the checkbox and nothing happened at all.
So it seems to be:
- a random issue that doesn't happen very often (race condition somewhere?)
- not browser-specific
- perhaps an early client-side JavaScript error, before the AJAX call is made to fetch the new fields
- possibly a problem for new site visitors only?
Comment | File | Size | Author |
---|---|---|---|
#28 | print_r_this.txt | 1.73 MB | fonant |
#25 | coupon-address-error-callback.txt | 3.11 MB | fonant |
Comments
Comment #1
rszrama CreditAttribution: rszrama commentedNo clue... I haven't personally seen the issue, so we'll just leave this open until we can get some steps to reproduce. It very well could be some other JavaScript on the page causing an error before the Ajax request runs. Can you share the link or does it need to remain private?
Comment #2
fonant CreditAttribution: fonant commentedIt's a tricky one!
The Commerce store is at http://www.thehealthybackbag.co.uk - it should be possible to reproduce the problem by adding one item to the basket and then going to the checkout page. But I haven't managed to reproduce it here, and others say everything is working for them too.
As I hear from other people who've seen the problem I'll post more info here.
Comment #3
rszrama CreditAttribution: rszrama commentedWow, that site looks awesome! Great work. : )
fwiw, I tested Add to Cart / the profile copy checkbox and it worked as expected. I'll keep an eye out and try making it fail in other browsers if possible.
Comment #4
fonant CreditAttribution: fonant commentedUseful new symptom information: the problem occurs if a coupon code is added using commerce_discount/commerce_coupon.
I can now reproduce the problem. Changing "My Shipping information is the same as my Billing information" now results in a 500 server error from the AJAX call.
So not random, it's a problem caused by commerce_discount/commerce_coupon!
The error message is:
Since a "Free Shipping" discount works fine, I suspect it's something to do with the additional line item that the discount/coupon module adds to the order.
I'll try to diagnose the cause further when I get a spare moment.
Comment #5
fonant CreditAttribution: fonant commentedComment #6
rszrama CreditAttribution: rszrama commentedThanks for the update! Moving to the Coupon project (but feel free to move it to the Discount project if it turns out to be an issue inthere).
Comment #7
fonant CreditAttribution: fonant commentedThree hours more research (this is hard to debug, there are so many function and method calls going on!):
Additional symptoms:
* Error occurs if a Discount Coupon has been applied to the order.
* If you re-apply the Discount Coupon a second time (resulting in "The coupon you have entered has already been applied to your order") then everything works fine.
The error is triggered by the AJAX call which in turn calls commerce_customer_profile_copy_validate() to validate the commerce_customer_profile_copy field in the checkout form. This validation function saves the order, and at some point during the commerce_order_save() an exception is caused and it all stops with a 500 error.
Comment #8
fonant CreditAttribution: fonant commentedOK, more info.
The problem seems to be that while validating the "The coupon you have entered has already been applied to your order" field the order is saved and refreshed and generally manipulated a great deal. Not sure why this is needed: there's an awful lot of code being run!
For some reason during this process the existing discount line item is being deleted and replaced with a duplicate one with a new ID, but the order in some places still refers to the original line item that is deleted so has no data.
Comment #9
fonant CreditAttribution: fonant commentedThe problem seems to stem from
commerce_discount_commerce_cart_order_refresh()
deleting and re-creating order discount line items. In the context of this particular AJAX call this results in the order becoming corrupted because it refers to the original discount line item which has been deleted.Comment #10
dpolant CreditAttribution: dpolant commentedI believe I fixed this by adding an empty check on the discount line items.
Discount module has a habit of churning through line items, so you always have to be super careful not to assume they actually exist while doing stuff in a cart refresh hook.
Check the latest dev branch.
Comment #11
fonant CreditAttribution: fonant commentedNope, still fails here.
Using:
If I apply a discount code to the order, using "My Shipping information is the same as my Billing information" causes a 500 error on the AJAX call, meaning customers cannot enter a separate shipping address.
The problem occurs if you:
The problem does not occur if you:
Comment #12
fonant CreditAttribution: fonant commentedMoving to commerce_discount, as this problem still occurs with a very simple discount and with commerce_coupon disabled.
Demonstration with simple site:
Running with:
Comment #13
fonant CreditAttribution: fonant commentedComment #14
fonant CreditAttribution: fonant commentedComment #15
joelpittetThanks for the demo @fonant! Is there any chance you can post what the PHP error log is spitting out from that 500 error?
Also is this still happening on the latest -dev?
If so I think we can likely create a test for this now that the automated tests seem to be working today.
Comment #16
fonant CreditAttribution: fonant at Fonant Ltd commentedWith:
I got:
EntityMetadataWrapperException: Unable to get the data property commerce_unit_price as the parent data structure is not set. in EntityStructureWrapper->getPropertyValue() (line 438 of /var/www/shared/drupal7/sites/all/modules/entity/includes/entity.wrapper.inc).
but with commerce_discount 7.x-1.x-dev (7.x-1.0-alpha6+2-dev) the error has gone!
Thank you for fixing this :)
Comment #17
joelpittetOh great news!
Comment #18
fonant CreditAttribution: fonant at Fonant Ltd commentedHmmm.. not quite. On my simple demo site the bug has gone away, but on a more complex site the bug still persists a little.
There still seems to be an initialisation problem, just the first time you want a different shipping address:
From then on the shipping address toggle works fine, but if you refresh the checkout page (or go to the next page and then back again) the problem returns.
Comment #19
joelpittetIs the discount code a using the coupon module? And what is the PHP error for the 500 error?
Comment #20
fonant CreditAttribution: fonant at Fonant Ltd commentedOK, I've updated my demo site to use coupon code for the discount, and the error is reproducible.
The error is slightly different now:
EntityMetadataWrapperException: Unable to get the data property type as the parent data structure is not set. in EntityStructureWrapper->getPropertyValue() (line 438 of /var/www/shared/drupal7/sites/all/modules/entity/includes/entity.wrapper.inc).
Comment #21
fonant CreditAttribution: fonant at Fonant Ltd commentedMore testing shows that the bug remains even with commerce_coupon 7.x-2.0-rc2+2-dev
Comment #22
joelpittetCan you use the -dev version instead of alpha5? alpha6 i better but the dev version has nice fix here for the wrapper cache issues #2540234: Order Wrapper updating on refresh creates stale EMW cache
What version of the coupon module are you using?
Comment #23
fonant CreditAttribution: fonant at Fonant Ltd commentedSorry, I was, gave the wrong version numbers above. My demo site has:
It's a lot better than it was: with a coupon code entered you still get a 500 error when trying to enter a different shipping address, but if you try again it works.
Comment #24
joelpittetAh thank you, it would be good to know where that error is originating. Could you add backtrace info to that exception?
includes/entity.wrapper.inc
Then we can find out what function is being called that is losing that property info.
It looks like 'type' is being checked on a non-object. And likely should be getBundle() call on a EMW but that won't resolve the issue.
Comment #25
fonant CreditAttribution: fonant at Fonant Ltd commentedHere's the backtrace - there's a lot!
Comment #26
joelpittetAwesome, that callstack doesn't have any commerce_discount functions in it. It looks like there may be an issue in commerce_donate from first glance.
Comment #27
joelpittet@fonant I think it's suffering from stale cache as well in the entity_metadata_wrapper, we were looking in to a fix here https://www.drupal.org/node/1343196#comment-10152572 though i think it would great to just remove that cache all together like they suggest.
I wonder though if you apply that patch that it may resolve the issue. Give it a try...
Comment #28
fonant CreditAttribution: fonant at Fonant Ltd commentedThanks for the ideas :)
Oddly although commerce_donate was once installed, it is no longer enabled and has been uninstalled. I'll check for remnants.
The patch linked to for entity_metadata_wrapper sadly doesn't help.
Here's a print_r($this, TRUE) from where the exception is raised.
Comment #29
joelpittet@fonant in self-interest but it "may" help, try this patch #2538812: When discounts are deleted on existing carts it's EMW related for commerce_discount.
Comment #30
joelpittet@fonant regarding commerce_donate, it was in the traceback/callstack you provided so it's being triggered. If you remove it and still get the error, can you post another traceback?
Comment #31
maxollerenshaw CreditAttribution: maxollerenshaw commentedHi,
I can replicate this issue every time when an order discount is applied, I've not tried with a coupon. I thought i'd add a comment here to describe the issue I've found but If I need to raise as a new bug let me know as it's separate to the coupon issue described above.
I created an order discount when the total amount is greater than 49.99 then to add a free product to the bag. When you uncheck the box to change shipping information I get the http status 500 error every time. When I disabled this discount unchecking the box worked fine.
My versions differ slightly:
Commerce Discount - 7.x-1.0-alpha4
Commerce Coupon - 7.x-1.0-beta7
Unfortunately my php knowledge isn't good enough to develop a solution so hopefully the info I've provided will help track down the issue quicker, I'd be more than happy to test out any patches should somebody write one.
Many Thanks
Max
Comment #32
joelpittet@maxollerenshaw please try to upgrade to the latest versions of discount and coupon and open a new issue if this problem persists.
There has been quite a few fixes since that release so it doesn't help us much to debug old alpha releases. Please try with the latest -dev release.
Comment #33
mglamanI can't replicate, it seems this is an issue with Commerce Coupon. It's happening with 2.x and 1.x versions in the comments. Marking needs more info for solid testing steps without Commerce Coupon. Otherwise I think we can mark "cannot reproduce" or kick over to that queue.
Comment #34
joelpittetClosing to triage the issue queue, reopen if you feel this still needs to be addressed. Assuming #33 is correct