I'm using Drupal 7.0
I have created a custom module that have 2 major responsabilities:
- Create a custom content type by code (that is not using the field api)
- Import content for that specified content type from a csv file.
This module used the function: drupal_form_submit($form_id, $form_state)
to import the content.
When I use my module to import content, I have the following errors:
Invalid offset supplied in field.attach.inc at line 198.
After doing a lot of investigation, I found some interesting stuff in the function:
function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array())
The above function is calling _field_invoke_get_instances($entity_type, $bundle, $options) (line 184)
This function return an array with all content type with all fields instance.
In my case, the Array returned for my content type is empty (no field instance in the array).
So, at line 189 of the _field_invoke function ($field_name = $instance['field_name']) :
The instruction is not valid because the offset 'field_name' doesn't exist.
I suggest that the function _field_invoke should be modified as follow:
Insert an if statement between line 188 and line 189 to verify the validity of the 'field_name' offset.
line 188 foreach ($instances as $instance) {
if (isset($instance['field_name'])) {
line 189 $field_name = $instance['field_name'];
Thanks in advance !
Comments
Comment #1
bnetsolutioninc commentedSorry, I changed the version to the current version used with my module. (Drupal 7.0)
Comment #2
xatoo commentedI confirm the existence of the bug in 7.x-dev. _field_invoke_get_instances might return empty arrays. Subsequently _field_invoke just assumes it contains a field name.
In my particular situation it results in the following error. It renders imports completely unusable for fieldable entities.
Fatal error: Cannot access empty property in /var/www/dev/modules/field/field.attach.inc on line 197
Call Stack:
Entity->save( ) ../mymodule.module:550
EntityAPIControllerExportable->save( ) ../entity.inc:168
EntityAPIController->save( ) ../entity.controller.inc:694
EntityAPIController->invoke( ) ../entity.controller.inc:356
field_attach_insert( ) ../entity.controller.inc:257
_field_invoke_default( ) ../field.attach.inc:898
_field_invoke( ) ../field.attach.inc:375
Comment #3
amanaplan commentedsubscribing
Comment #4
xatoo commentedAccording to http://drupal.org/node/45111, this bug qualifies as major.
The error is avoided, when I add the following code to to modules/field/field.attach.inc:188
But then a secondary error occurs.
When I add a similar piece of code there, it all works fine.
Their main divider in the call-stack is _field_info_collate_fields() in modules/field/field.info.inc. I suspect this function to be the source of the bug, but I don't have enough insight into the Field module to figure it out.
Comment #5
catchThis isn't possible:
If $instances is an empty array, then the foreach will never reach that section of code. Something else might be going on, but the description doesn't sound right to me at all.
Please post the output of var_dump($instances); before it goes into that loop, and var_dump($field) just before the notice is thrown.
Comment #6
now100handed commentedI'm seeing this on user add pages and order pages in Ubercart.
I'm using Ubercart 3 and Drupal 7 and get this error when I tail httpd error_log.
PHP Fatal error: Cannot access empty property in modules/field/field.attach.inc on line 197The page fails to render I just get a 500 error. Refreshing the page I came to before the error presents me with
Notice: Undefined index: field_name in _field_invoke() (line 188 of /var/www/html/kelderman/drupal/modules/field/field.attach.inc).Comment #7
Anonymous (not verified) commentedIm running D7.7 and have the same error when trying to create content(my own entity) without fields.
Comment #8
Anonymous (not verified) commentedInstances actuaey are NOT empty array. They are
array('entity_name' => array());so the foreach will run once for the entity_name key.The fix can be done by---
Ok, Ive found the problem. In your entity add/edit form you have to set the bundle key in your entity object that you are providing for field_attach_form as second argument. So for node it is 'type' ie.
Comment #9
Anonymous (not verified) commentedI tink we can close this issue.
Comment #10
makara commentedThe error is easy to re-produce in 7.x. I don't know about 8.x.
Say a content type does not have a field named "field_random". But you want to display the field with
You got "Fatal error: Cannot access empty property".
This is because in the
function _field_invoke_get_instances()generates
array(0 =>NULL).Comment #11
makara commentedAdditions:
The field "field_random" needs to be existing but doesn't bundle to the content type.
Comment #12
makara commentedDrupal 8 is the same.
I have a simple patch here - adding an "array_filter()" because field_info_instance() can return NULL.
No patch for the tests yet.
Comment #13
makara commentedComment #14
catchWhy would you have code that does:
in the first place? If the code is wrong we shouldn't silently fail.
Comment #15
drunken monkeyI can confirm this bug exists, and currently bugs me with Views. Fatal errors aren't a nice way to fail, even though it could be argued the code is „wrong“.
Attached is my patch that fixes this, which seems to me to be slightly more straight-forward than #12, but I'd be fine with either. In any case, the patch applies cleanly on both D7 and D8.
@ catch: The context this occurs in for me is, as said, in Views. I add a field that is only present on some content types to the view. The view calls
field_view_field()-> BOOM!Of course, now that I know this, I can just check whether the field is present – but this was quite a drag to debug, and if we can fix it that easily, why not? Nothing's gonna explode just because we silently fail when people want to view a non-existing field. On the contrary, things are already exploding when we throw fatal errors all over the place in such a case.
Comment #16
catchWell what if I'm developing and remove a field instance, with current head it inform me that I left a crufty call to field_view_field() in, now there is no warning at all. Throwing an exception rather than the fatal might be fine though.
Comment #17
makara commentedIf the field doesn't exist, it just displays nothing without errors. Because you got
in the
function field_view_field(). Only if the field exists but there's no instance, it fails. IMO It would be logically better if we have something likeBut it's not easy to check it there. And I think it doesn't make sense for the
function _field_invoke_get_instances()to return anarray(NULL). Thus the patch.Comment #18
drunken monkeyYes, code-wise at least this makes no sense. You could argue that we should throw an exception or flag an error in other ways, but returning false results, not matching the function's contract, surely isn't the way to go.
And yes, if you don't get any warning or error for completely inexistent fields, this is additionally inconsistent. To me, this has much more the appearance of being an oversight than really having the attention to fail and inform the user.
Also, for lots of other code we also don't have any errors in such cases. Try loading a number of nodes with partly inexistent NIDs, for example. When developing, just watch what you're doing and you're fine.
Comment #19
David_Rothstein commentedI ran into this problem with Views too.
Here is the patch rerolled for D8, and with tests. The tests help demonstrate the inconsistency in the current behavior; if we want there to be an error thrown in this scenario that might be reasonable (although probably D8-only), but the fact that with the current codebase the first test returns an empty array and the second throws a PHP fatal error definitely doesn't make sense, so for now they should both return an empty array for consistency (which is what the patch makes them do).
Comment #20
David_Rothstein commentedBy the way, here's the Views issue I came across: #1461536: Fatal error when using aggregation and a field is not attached to all entities in the view
It seems like it's possible to work around this in Views if necessary, but I think it's a core bug so it's better to be fixed here.
Comment #21
dave reidRan into this with a client project as well. The patch looks good and fixes the issue and the tests make sense to me.
Comment #22
tim.plunkettRerolled for PSR-0 tests and removed t() from assertion messages.
Leaving at RTBC.
Comment #23
catchOK I can live with this, but can we at least add a watchdog() call in the 8.x patch so there's not a silent failure here?
Comment #24
dave reidThen we'd have to build in logic that determines if parameters are invalid, of if a bundle has no field attached yet, or if the field doesn't exist. I don't agree with adding a watchdog call here because an empty array is valid output.
Comment #25
catchI don't think we need all that.
If this doesn't return anything, then log to watchdog.
Comment #26
dave reidHrm, I just agree to disagree. Tim, David: opinions?
Comment #27
tim.plunkettTo help myself decide what I thought about logging something to watchdog, I thought about what it would say.
The best I came up with was "This content type has no fields, thought you should know."
There's nothing wrong with having no fields on a content type.
I think this is fine as is.
Comment #28
catchThe problem isn't that you have a bundle with no fields, it's that you're trying to render a field that doesn't have an instance on a content type (or retrieve an instance on a bundle that doesn't have the field assigned). That's exactly the sort of error which can lead to headbanging and debugging so it'd be good to give people a clue that they're doing something strange. Also field API is full of very specific exceptions that do this in lots of other circumstances.
If we could throw a fatal error previously, I don't see why it's impossible to log some kind of error now. Back to CNW one more time.
Comment #29
rudiedirkx commented(OP coding format+)
Comment #30
pwolanin commented19: 1161708-field_invoke-trouble-19.patch queued for re-testing.
Comment #32
David_Rothstein commentedIs this issue still relevant for Drupal 8?
That is true if you trigger this via field_view_field(), but aren't there many ways to call this function besides that, any many of them aren't error conditions?
So at first glance I don't think we'd want a watchdog() call or similar inside _field_invoke_get_instances() itself. Maybe inside field_view_field()...
Comment #41
catchThis is no longer relevant for Drupal 9, moving back to Drupal 7.