On a site that used comments, but had Comment module disabled prior to the D6 to D7 upgrade, the Comment module cannot be enabled after the upgrade.
Trying to enable Comment resulted in this:
FieldException: Attempt to create an instance of field comment_body on bundle comment_node_page that already has an instance of that field. in field_create_instance() (line 673 of /home/ben/workspace/d7t/modules/field/field.crud.inc).
Bangpound suspects the upgrade to d7 created the field and didn't let the system table know about it.
I used a devel-generated Drupal 6 database to test upgrading (for the taxo as field patch) if others have difficulty reproducing this error.
I think this may be related to #877690: Cannot upgrade Drupal core if the comment module is enabled (and in any case, my test was done after this went in, i checked the code to be sure).
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | comment-body-890210-24.patch | 3.54 KB | bjaspan |
| #15 | drupal-890210.patch | 1.13 KB | manuel garcia |
| #13 | commentbug_debug_formatted.txt.zip | 168.43 KB | manuel garcia |
| #12 | d6head.sql_.zip | 38.18 KB | manuel garcia |
| #12 | d6head_upgradedtod7.zip | 56.09 KB | manuel garcia |
Comments
Comment #1
manuel garcia commentedOK, I can confirm this bug, steps taken:
No errors were encountered during the update process.
FieldException: Attempt to create an instance of field comment_body on bundle comment_node_page that already has an instance of that field. in field_create_instance() (line 673 of /home/manuel/htdocs/d6head/modules/field/field.crud.inc)./comment/reply/1, which returns a Page not found errorOther information:
Add new commentlink is added on teaser view, wich also ends up in a page not found obviously.Comment #2
manuel garcia commentedComment #3
Letharion commentedI'm working on a different issue, that appears to be very similar.
http://drupal.org/node/890128
Comment #4
Letharion commentedSorry, re-adding the tag.
Comment #5
sfyn commentedNext time someone reproduces this error, can they post the database dump so we can all be working from the same dataset?
Comment #6
manuel garcia commented@sfyn I worked from a fresh install of d6-dev (2010-Aug-12), and upgraded to latest d7-dev (2010-Aug-23)
Comment #7
manuel garcia commentedFor the record, I'm uploading the DB dump of the d7 database upgraded, with comment module enabled (after all my tests in my comment above).
Comment #8
bjaspan commentedIn comment.install, comment_enable() we have:
Since the bug report says the problem occurs while enabling the comment module, this would be a prime suspect, except the code checks whether the instance already exists. But the bug has to be that one place is creating the instance and another place is not checking before trying to create it again.
Comment #9
manuel garcia commentedComment #10
manuel garcia commentedResults of repeating the process, and executing debug_backtrace(); on line 672 of field.crud.inc, like this:
Comment #11
manuel garcia commentedComment #12
manuel garcia commentedIm uploading:
d6head: fresh install of d6 database dump, with comment module disabled, ready to be upgraded.
d6head_upgradedtod7: database dump of the d7 db, just after upgrading to it, ready to enable the comment module and test the bug.
user 1: admin:admin
Comment #13
manuel garcia commentedThe results of the backtrace actualy formatted so a human can use it....
Comment #14
sutharsan commentedWorth noting: with devel module installed this error does no longer occur! To be continued ...
Comment #15
manuel garcia commentedOK, after long debugging along side Sutharsan here in the drupalcon codesprint, we can have some results.
Apparently the function field_read_instance returns a positive result when called in field_create_instance(), at least in this case.
I tested to see whether field_info_instance would also return a positive result, when we are sure that the field instances do not exist (since they don't show in the comment form), and the function returns false in the situation that this bug occurs, which is what should happen.
So the attached patch does something very simple, it uses field_info_instance to check whether the instance already exists or not, instead of field_read_instance.
Ive tested creating a new content type, and debugging showed that the function did return info on field instances already there for page and story, but not for the new content type, so the new content type got the comment body field attached as expected.
We could be way off here or breaking something else, so any guidance would be very welcomed!
Comment #16
manuel garcia commentedFor the record, I've print_r'ed $prior_instance in line 670 of field.crud.inc
field_read_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);And in each case, it seems to return the result from the comment_node_page bundle.
I am totally lost as to why
field_read_instanceis returning something, butfield_info_instancedoes not.Comment #17
manuel garcia commentedMore updates,
Looks to me that my patch is probably not the way to go, I have been doing some more digging, and upon upgrade to d7, there are two entries in table field_config_instance for comment_body, one for comment_node_page, and one for comment_node_blog.
So, next question that should be asked is, why then are the fields not being added to the comment forms?
Comment #18
sutharsan commentedFunther investigation on the data that field_info_instance() revealed that field_info_instance() is NOT the way to go. field_info_instance() will only return entity data of enabled modules. And at the time the function is called, the module is not yet (fully) enabled.
Changing the status back to 'active' since a totally different solution here.
Comment #19
bjaspan commentedI'm working on this.
Comment #20
bjaspan commentedThe issue is that the cached field info returned by _field_info_collate_fields() does not contain the comment_body instances. Thus in comment_enable(),
the field_info_instance() test returns false and the code tries to create a new one. So why doesn't comment_body exist in the cached field info? My guess is that it is because the field and instances are created inside a comment update hook, during which the comment module (which defines the comment entity) is not enabled yet, and so the comment_body field and instances are marked inactive or something. Presumably exactly the same problem would occur for every update function that creates fields and instances for its own entity type, which led me to suspect that comment module is the LAST module to do so during the D6->D7 upgrade.
To confirm, I put a print_r($instance) statement in field_create_instance() and, sure enough, the comment_body fields are the last ones created.
So this is probably a cache clearing bug, nothing specific with comment.module. I'll look more into it later, now it is time for dinner.
Comment #21
bjaspan commentedI confirmed that this is not a problem with comment.module at all. The issue is that during comment.module's update functions, comment.module is not enabled yet. The update function creates the comment_body field and its instances, but it creates it on the 'comment' entity type which is not defined because comment.module is not enabled. The final call to _field_info_collate_fields() during this whole process occurs still during the update function, so the last version of field info that gets cached does not have the comment_body field in it. Apparently, the cache remains uncleared up through submitting the modules page enabling the comment module, which tries to re-create the comment_body field and its instances because its check (using Field Info API functions) for whether they already exist fails because the cache is wrong.
This will happen to whichever module creates a field and instances on its own entity last during the install process. comment.module just happens to be last.
Clearing all caches before enabling the module works around the problem.
I'm not quite sure what system is "at fault" here. One obvious fix is to clear all caches after every update function, though that might be slow, OTOH it seems pretty essential for correct functioning of arbitrary modules. However, it occurs to me that I'm surprised field_create_instance() works at all when given an entity type name that does not exist yet; it "should" just fail immediately. If it did, though, we'd have a chicken-and-egg problem because a module's entities can never exist before the module is enabled and the update functions run before the module is enabled; under this condition all modules that create a field on its own entity type, not just the last, would fail.
So I'm not sure what to do besides clearing all caches after every update function. The only alternative I can think of is to somehow force a module's entity type to exist before the module is enabled (so hook_entity_info() runs)... but that would only solve the problem for entity types, not for any other kind of hook exported by the module and cached by any API function called during an update function.
Actually I think the only *complete* solution is to declare an update function that runs after the module is enabled; it will then be up to the module author to make sure that works okay. This may be too big a change for D7 now, in which case clear caches after every update and not "fixing" field_create_instance() to be more strict is the best approach for now.
Comment #22
bjaspan commentedSo clearly I was asleep last night when I wrote the above comment. The solution here is to move the code to create the comment_body field and instances from comment_enable() to comment_install(). That way, either the update function or the install function will create the field/instances, but not both.
Comment #23
bjaspan commentedOh, this looks like fun:
Comment #24
bjaspan commentedThis patch moves comment_body field and instance creation to comment_install(). It seems to work for me but the @todo I deleted suggests it will cause test failures. We'll see.
Comment #25
bjaspan commentedWell, okay... now what? Should we conclude that whatever problem previously caused field and instance creation in hook install to fail has been fixed?
Comment #26
mlncn commentedNo errors on updating a Drupal 6 database, and no errors on enabling the comment module.
On the other hand, none of the 1,879 comments that had existed in Drupal 6 database (linked in the original post) show up on administration page (admin/content/comment). The comments do exist on node pages, so i think this patch is a success and the failure to list published comments is separate.
Comment #27
mlncn commentedI cannot find the issue elsewhere, and new comments i create do appear as published comments at admin/content/comment, so there is something wrong with the comment upgrade path still. I'd say it's a non-critical bug and i'm guessing it's separate enough from what bjaspan fixed to be dealt with in a followup issue, though.
Comment #28
bjaspan commented#891250: "View comments" permission not working after upgrade to Drupal 7 addresses the problems of comments not appearing after the upgrade. With both patches applied, comments work across the upgrade. I marked the other patch RTBC but this one is mine so I can't.
Comment #29
mlncn commentedIt's ready! Code review: It's the exact same code that was already there, in a new place, with the TODO to move it removed :-)
Comment #30
tstoecklerThe patch looks good and is basically moving code to where it really belongs, but I didn't try it out, so I won't RTBC.
Comment #31
marcingy commentedMarking as RBTC as the original reporter seems happy with the patch provided
Comment #32
webchickAwesome sleuthing, folks! Committed to HEAD!
Comment #33
manuel garcia commentedI agree, the patch makes sense.
Also thanks bjaspan for explaining what was going on, we were going nuts in the code sprint :X
Comment #34
manuel garcia commentedreverting status (crossposted) yay fixed!