Download & Extend

Unable to add new content with empty upgraded image/file field

Project:Drupal core
Version:7.19
Component:file system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review

Issue Summary

If I am posting this in the incorrect place, please direct me to the correct issue queue.

In our D6 site, we were using IMCE CCK Image with IMCE browser. I used imceimage_2_filefield to convert to FileField and then upgraded to D7. There were no errors in the image migration and I am able to see images on migrated content - including editing, removing, and adding new images.

When I try to add a new page with nothing in the optional image field, I receive the following errors:

The website encountered an unexpected error. Please try again later.
Notice: Undefined property: stdClass::$fid in file_usage_add() (line 654 of /var/www/domain/includes/file.inc).
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'fid' cannot be null: INSERT INTO {file_usage} (fid, module, type, id, count) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4); Array ( [:db_insert_placeholder_0] => [:db_insert_placeholder_1] => file [:db_insert_placeholder_2] => node [:db_insert_placeholder_3] => 4075 [:db_insert_placeholder_4] => 1 ) in file_usage_add() (line 661 of /var/www/domain/includes/file.inc).

When I include the optional image in the page, it saves without a problem. Interesting to mention, even with the error, if I look at new content, the page was created. The file_usage error upon save makes it look like it was not.

This repeats itself creating new content with every content type that contains a migrated image field.

In troubleshooting, I found that if I add the same field to my content type and remove the migrated image field, everything works fine. However doing this, I lose years worth of image file associations.

An example of this is: I have a "Kids" content type. If I remove the existing "field_image" and add the same exact "field_image" back in, adding new content doesn't require data in field_image to save correctly.

Can someone help me troubleshoot the existing content types with migrated image fields?

Comments

#1

Title:Unable to add new node with IMCE field after upgrade to D7 for existing Content Types» Unable to add new content with migrated Image field after upgrade to D7
Project:IMCE» Drupal core
Version:7.x-1.5» 7.14
Component:Code» image system

Moving to core since I'm not sure if this is core or module specific.

#2

I've been able to determine using Devel Backtrace that the value given for the first/0 arg is actually an incorrect array of imceimage file descriptors. Here is the submission being passed to file_usage_add() before the error is triggered:

14: file_usage_add() (Array, 2 elements)

    file (String, 21 characters ) includes/file.inc:654
    args (Array, 4 elements)
        0 (Object) stdClass
            imceimage_path (String, 0 characters )
            imceimage_width (String, 0 characters )
            imceimage_height (String, 0 characters )
            imceimage_alt (String, 0 characters )
        1 (String, 4 characters ) file | (Callback) file();
        2 (String, 4 characters ) node
        3 (String, 4 characters ) 4092

So now I'm trying to trace back the point where this enters the picture. After running IMCEImage_2_filefield module and then upgrading to Drupal 7, I didn't think these references to IMCE should be used any more.

Looking back further in the backtrace, I see that the first mention of IMCEIMAGE is passed in step 12: image_field_insert:

12: image_field_insert() (Array, 2 elements)

    file (String, 33 characters ) modules/image/image.field.inc:250
    args (Array, 8 elements)
        0 (String, 4 characters ) node
        1 (Object) stdClass
        2 (Array, 17 elements)
        3 (Array, 15 elements)
            weight (String, 2 characters ) -1
            label (String, 11 characters ) Event Image
            widget_type (String, 17 characters ) imagefield_widget
            description (String, 0 characters )
            default_value (Array, 1 element)
                0 (Array, 4 elements)
                    imceimage_path (String, 0 characters )
                    imceimage_width (String, 0 characters )
                    imceimage_height (String, 0 characters )
                    imceimage_alt (String, 0 characters )
            widget (Array, 5 elements)
            display (Array, 7 elements)
            settings (Array, 9 elements)
            required (Integer) 0
            id (String, 3 characters ) 107
            field_id (String, 2 characters ) 32
            field_name (String, 17 characters ) field_image_event
            entity_type (String, 4 characters ) node
            bundle (String, 5 characters ) event
            deleted (String, 1 characters ) 0
        4 (String, 3 characters ) und
        5 (Array, 2 elements)
            ∞ (Recursion)

So now I just need to figure out where the IMCEIMAGE reference is coming from and why the correct FID array is not being used.

#3

I'm getting exactly the same error in exactly the same situation. Did you get to the bottom of it?

#4

Unfortunately, no. I still don't have a solution, other than adding in the image and then removing it after the node created. Glad to know it is not just me, though :)

#5

Similar: #905108: Integrity constraint violation: 1048 Column 'fid' cannot be null

My error:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'fid' cannot be null: INSERT INTO {file_usage} (fid, module, type, id, count) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4); Array ( [:db_insert_placeholder_0] => [:db_insert_placeholder_1] => file [:db_insert_placeholder_2] => node [:db_insert_placeholder_3] => 12459 [:db_insert_placeholder_4] => 1 ) in file_usage_add() (line 661 of /Users/kenorb/Sites/XXX/docroot/includes/file.inc).

But I'm not using image, just a file field.
It happens when submitting the node using ctools wizard multistep.
None of the files were posted.

This could be related as well:
#1163740: PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 2: INSERT INTO {file_managed}

#6

Following code (from Drupal core) in my specified case:

<?php
function file_usage_add(stdClass $file, $module, $type, $id, $count = 1) {
  if (
is_null($file->fid)) {
   
var_dump($file, $module, $type, $id, $count); exit;
  }
 
db_merge('file_usage')
    ->
key(array(
     
'fid' => $file->fid,
...
?>

returns:
object(stdClass)[311] // <!-- 1st argument is EMPTY object
string 'file' (length=4)
string 'node' (length=4)
string '12461' (length=5)
int 1

Backtrace:

'function' => string 'file_usage_add' (length=14)
'function' => string 'file_field_insert' (length=17)
'function' => string '_field_invoke' (length=13)
'function' => string 'field_attach_insert' (length=19) (node)
'function' => string 'node_save' (length=9) (my module)

Problem:
node which is saved contains somehow empty/null value:

public 'field_file' =>
    array
      'und' =>
        array
          0 => null

This is because:
When I'm submitting step which has file field on the page, the following variable is _POSTed to $form_state:

<?php
array
 
'previous' => string 'Back' (length=4)
 
'next' => string 'Continue' (length=8)
 
'field_file' =>
    array
     
'und' =>
        array
         
0 =>
            array
             
'_weight' => string '0' (length=1)
             
'fid' => int 0
             
'display' => string '1' (length=1)
             
'description' => string '' (length=0)
             
'upload_button' => string 'Upload' (length=6)
             
'remove_button' => string 'Remove' (length=6)
             
'upload' => string '' (length=0)
 
'form_build_id' => string 'form-xxx' (length=48)
 
'form_token' => string 'xxx' (length=43)
 
'form_id' => string 'xxx' (length=31)
 
'op' => string 'Continue' (length=8)
?>

, after that I'm copying values from field_file to my $node object, so at this point everything is perfect.
The problem is when those details are loaded from cache and are damaged by _field_invoke_multiple().

It happens when I'm doing preview of the node by following code (#1622952: The right way to programatically render the preview of node object before the creation):

<?php
  $node
= ctools_object_cache_get('foo', 'node');
 
$node->in_preview = TRUE;
 
_field_invoke_multiple('load', 'node', array(NULL => $node)); // THIS function did some changes to $node object !
 
field_attach_prepare_view('node', array(NULL => &$node), 'full'); // lets field types and formatters load additional data needed for display
 
$build = @node_view($node, 'full');
// in different function I've:
$node = ctools_object_cache_get('foo', 'node');
node_save($node);
// here I've the fatal error, because the data in $node has been overridden by _field_invoke_multiple()
?>

and following line in that function (_field_invoke_multiple):
<?php
$entity
->{$field_name}[$langcode] = $grouped_items[$field_id][$langcode][$id];
?>

is overriding the field values, changing field_file array to NULL.

XDebug snapshot:

<?php
$langcode
= 'und' modules/field/field.attach.inc:363
$entity
= class stdClass { public $type = 'xxx'; public $workflow = 5; public $status = 1; public $promote = 0; public $sticky = 0; public $uid = '181'; public $created = 1341591323; public $revision = FALSE; public $comment = '0'; public $field_file = array ('und' => array (0 => array ('_weight' => '0', 'fid' => 0, 'display' => '1', 'description' => '', 'upload_button' => 'Upload', 'remove_button' => 'Remove', 'upload' => ''))); public $in_preview = TRUE } modules/field/field.attach.inc:364
$id
= '' modules/field/field.attach.inc:364
=> $entity->field_file['und'] = array (0 => NULL) modules/field/field.attach.inc:366
?>

I've fixed my problem by cloning ctools cached the object, See: #1676696: ctools_object_cache_get() returns reference, instead of clone
But still the question is, why _field_invoke_multiple is overriding the node values (some of them to NULL) when doing node preview.

#7

Category:support request» bug report

Deescription suggests a bug, changing category.

#9

Version:7.14» 7.15

I just upgraded to Drupal 7.15 and the error remains the same.

Have you found any solutions yet, Aangel or Kenorb?

#10

Version:7.15» 7.16

Hi Guys, I'm now working on the same site @aangel found this problem on, and I'd like to get to the bottom of it. To recap, we are working with a D7 site that has been upgraded from D6. Creating a node with a migrated image field on it throws errors when the image field is left empty:

PHP Notice

Notice: Undefined property: stdClass::$fid in includes/file.inc on line 654

PDO Fatal:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'fid' cannot be null: INSERT INTO {file_usage} (fid, module, type, id, count) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4); Array ( [:db_insert_placeholder_0] => [:db_insert_placeholder_1] => file [:db_insert_placeholder_2] => node [:db_insert_placeholder_3] => 361 [:db_insert_placeholder_4] => 1 ) in file_usage_add() (line 661 of includes/file.inc).

#11

I'm getting the same error. Drupal site was migrated from Drupal 6, and I've used imceimage before. Now it is exactly as in #2. I can not have file field, which was migrated from imceimage field, to be empty, for it gives error message as in Issue Summary

#12

Version:7.16» 7.17
Component:image system» file system

I'm up to 7.17 now, and having this problem on files as well as images. Any file or image field that has been upgraded from D6 to D7 throws PDO errors when left blank. I'm not sure what the difference is between the D6 upgraded fields, and why this isn't an issue for newly-created fields in D7. But what is happening is that a "file" made up of the array below ends up getting passed into file_field_insert().

<?php
Array
(
    [
embed] =>
    [
value] =>
)
?>

In my case, that "file" was passed in from _field_invoke and in the case of #6 it was passed in from _field_invoke_multiple.

#13

Title:Unable to add new content with migrated Image field after upgrade to D7» Unable to add new content with empty upgraded image/file field

better title :)

It looks like there is already a hook-like function that allows field types to define their primary field, and allow the field to be set as "empty" when that primary field is blank. File module uses it: file_field_is_empty.

Unfortunately, this function is only called from one place (_field_filter_items) and that function is never called in my case, and I expect not for #6 as well.

The reason this function is never called is because _field_filter_items is only called from within the default field functions for the two ops validate and submit, but those functions only get called when the $options array passed into _field_invoke contains 'default' => TRUE.

The default value for 'default' is FALSE. When the default is false, it causes Drupal to search for module-specific op functions like image_field_validate and file_field_validate (which don't exist) instead of using field_default_validate.

Since these functions don't exist, no function is run on this data at all, and the entire contents of the array get sent along to the next step.

#14

I think that #1443158: file_field_presave assumes that a file object has been loaded may resolve this, likely this is a duplicate of that issue.

#15

Status:active» needs review

No, it's not related.

At the time file_field_presave is run $items is just an empty array for me, so the patch #1443158: file_field_presave assumes that a file object has been loaded makes no difference in this case.

Maybe I can use the same approach for file_field_insert though, since it's not safe to assume that $items are properly formatted before they get here.

This patch seems to do the trick.

AttachmentSizeStatusTest resultOperations
core-save_upgraded_empty_fields-please-1627860-15.patch637 bytesIdlePASSED: [[SimpleTest]]: [MySQL] 39,471 pass(es).View details | Re-test

#16

If at the time of presave $items is an empty array, but at insert, it's not, then I'm not sure what core should actually be doing. Something is injecting invalid data inbetween those times. Presave should be the proper place to fix it...

#17

Well, the only module I am using that implements hook_field_insert is media, and it's implementation is almost exactly the same as file_field_insert. (none implement hook_field_presave).

What comes between presave and insert?

#18

Status:needs review» needs work

The last submitted patch, core-save_upgraded_empty_fields-please-1627860-15.patch, failed testing.

#19

Testing #15.

I could easily reproduce it via: drush -y generate-content --types=advert 10
Now instead of:

array_flip(): Can only flip STRING and INTEGER values! entity.inc:178                                                                                                                                                                                              [warning]
array_flip(): Can only flip STRING and INTEGER values! entity.inc:178                                                                                                                                                                                              [warning]
WD node: PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'fid' cannot be null: INSERT INTO {file_usage} (fid, module, type, id, count) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2,            [error]
:db_insert_placeholder_3, :db_insert_placeholder_4); Array
(
    [:db_insert_placeholder_0] =>
    [:db_insert_placeholder_1] => file
    [:db_insert_placeholder_2] => node
    [:db_insert_placeholder_3] => 3
    [:db_insert_placeholder_4] => 1
)
in file_usage_add() (line 661 of /home/ubuntu/docroot/includes/file.inc).

I see:
array_flip(): Can only flip STRING and INTEGER values! entity.inc:178                                                                                                                                                                                              [warning]
array_flip(): Can only flip STRING and INTEGER values! entity.inc:178                                                                                                                                                                                              [warning]
array_flip(): Can only flip STRING and INTEGER values! entity.inc:178                                                                                                                                                                                              [warning]
WD node: PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'uri': INSERT INTO {file_managed} (filesize, status, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2);     [error]
Array
(
    [:db_insert_placeholder_0] => 0
    [:db_insert_placeholder_1] => 1
    [:db_insert_placeholder_2] => 1355846014
)
in drupal_write_record() (line 7036 of /home/ubuntu/docroot/includes/common.inc).

#23

Version:7.17» 7.19
Status:closed (duplicate)» needs review

I can confirm that #15 solves the problem for med on a migrated file field from D6 --> D7. That patch seems to fix problems for some people. Shouldn't it just be commited for it self in stead of combining patches which fixes several problems (which some I do not experience?)? No 15 is RTBC for me.

#24

I still think that something inserting an invalid value between hook_file_presave() and hook_file_insert() means you have something else wrong that shouldn't be hidden by core.

#25

same problem here