Problem/Motivation

All 'file' field usages belonging to an entity are deleted when an entity translation is deleted. The deletion of an entity translation should decrement the file usage only vir file fields of contained by that translation.

Steps to reproduce:

  1. Create a content type with an image field
  2. Enable translation for your content type and image field
  3. Create a new node in English, (including uploading a file to the image field)
  4. Add a translation of the node (Spanish, let's say). You can leave the same image in place, or use a different one, shouldn't matter.
  5. Delete just the Spanish translation of the node.
  6. Observe that the file_usage entry for the referenced file has been completely wiped out, despite the file still being in use by the English version. The status flag in file_managed also gets set to 0 making it eligible for cleanup.

This happens because FileFieldItemList::delete() is not aware of entity translations. Entity translation deletion is piped throughFileFieldItemList::delete() as a normal entity deletion. The bug is revealed by the test-only patch.

Because this bug leads to data loss, is marked as Critical.

Proposed resolution

Fix it.

Remaining tasks

None.

User interface changes

None.

API changes

None.

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

azinck created an issue. See original summary.

azinck’s picture

Issue summary: View changes
grahl’s picture

Seeing this as well, due to the data loss which silently occurs, this is at least major if not critical.

azinck’s picture

Priority: Major » Critical

Yeah, I'm going to bump to critical.

claudiu.cristea’s picture

Assigned: Unassigned » claudiu.cristea

I'm writing a test.

grahl’s picture

Attached is a patch which fixes my immediate problem.

With that check, loosely adapted from the postSave() function in place my translation only gets a decrement in file_usage of 1 instead of all. Though I might have queried the entity api incorrectly there since the deletion of the original doesn't actually seem to force the other half of the if statement.

The latter shouldn't be a big issue if the counter would not increment incorrectly. I am consistently seeing a count of 3 when a translation is added to the original instead of 2 (or is that intentional?).

claudiu.cristea’s picture

Assigned: claudiu.cristea » Unassigned
Issue tags: -multilingual, -FileField
FileSize
2.58 KB

Yepp, this test reveals the bug.

claudiu.cristea’s picture

Status: Active » Needs review
claudiu.cristea’s picture

And the patch (inspired from #7).

azinck’s picture

Seems to me that we need to actually count up all the usages by all of the revisions of this entity in the given language. I don't think #10 is going to be sufficient. See #2639352: File records, files themselves lost in translation

The last submitted patch, 7: data_loss_deleting_a-2787187-7.patch, failed testing.

The last submitted patch, 8: 2787187-8-test-only.patch, failed testing.

claudiu.cristea’s picture

azinck’s picture

Yes, my mistake. Copy pasted wrong issue twice! Thank you.

claudiu.cristea’s picture

Component: file system » file.module
Issue summary: View changes
Issue tags: +data loss

Fixed the IS.

Mile23’s picture

Status: Needs review » Needs work

Given #11 and #14 I'm setting this to 'needs work.'

claudiu.cristea’s picture

Status: Needs work » Needs review

@Mile23, can you, please, be more specific? I don't think something else needs to be done here. Removing usages added by revisions is fixed in #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger, not here. As I recall is fixed by deleting the revisions and that is piped thorough \Drupal\file\Plugin\Field\FieldType\FileFieldItemList::deleteRevision.

xjm’s picture

@catch, @effulgentsia, @alexpott, @Cottser, and I agreed that this is definitely a critical bug because of the data loss issue.

Fabianx’s picture

Status: Needs review » Needs work

Overall looks great to me, but:

+++ b/core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php
@@ -81,9 +81,12 @@ public function delete() {
+    $count = (int) ($untranslated->language()->getId() != $entity->language()->getId());

While this is pretty clever casting logic, it would be better to write this explicitly, as it is very hard to understand on a first glance.

claudiu.cristea’s picture

Status: Needs work » Needs review
FileSize
3.63 KB
933 bytes

@Fabianx, thank you for review.

While this is pretty clever casting logic, it would be better to write this explicitly, as it is very hard to understand on a first glance.

Made it more explicit.

dawehner’s picture

+++ b/core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php
@@ -81,9 +81,12 @@ public function delete() {
+    $count = $untranslated->language()->getId() === $entity->language()->getId() ? 0 : 1;

Couldn't you use isDefaultTranslation actually?

claudiu.cristea’s picture

FileSize
900 bytes
3.54 KB

Sure, forgot that method.

claudiu.cristea’s picture

Improved the comment.

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Sweet, much better now!

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to all three 8.x branches, thanks!

  • catch committed a1b670f on 8.3.x
    Issue #2787187 by claudiu.cristea, grahl, azinck: Data loss: Deleting a...

  • catch committed 37e041d on 8.2.x
    Issue #2787187 by claudiu.cristea, grahl, azinck: Data loss: Deleting a...

  • catch committed 81bb5b8 on 8.1.x
    Issue #2787187 by claudiu.cristea, grahl, azinck: Data loss: Deleting a...
Gábor Hojtsy’s picture

Issue tags: +D8MI, +language-content

Yay, thanks!

  • catch committed fb18e30 on 8.3.x
    Revert "Issue #2787187 by claudiu.cristea, grahl, azinck: Data loss:...

  • catch committed 8333f01 on 8.2.x
    Revert "Issue #2787187 by claudiu.cristea, grahl, azinck: Data loss:...

  • catch committed 5583f85 on 8.1.x
    Revert "Issue #2787187 by claudiu.cristea, grahl, azinck: Data loss:...
catch’s picture

Status: Fixed » Needs review

Test failed in HEAD, reverted and sending for re-test on all three branches.

Status: Needs review » Needs work

The last submitted patch, 24: 2787187-24.patch, failed testing.

The last submitted patch, 24: 2787187-24.patch, failed testing.

claudiu.cristea’s picture

Version: 8.1.x-dev » 8.2.x-dev
Status: Needs work » Needs review
FileSize
2.25 KB
5.79 KB

This is amazing. Those 2 tests are passing now in 8.2.x and 8.3.x HEAD because of the combined effect of two bugs that are compensating each other: this one and #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger. This bug releases too many file usages while the other wrongly add them back making, together, a zero balance. But because #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger is not yet committed, the effects of the 2 bugs are not compensating anymore.

I propose to temporarily get rid about that failed test till #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger. In that patch we need to restore the lines. See the interdiff for details.

The behavior has changed after #2490136: Enable revisions by default has been committed.

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC. As discussed with @catch on IRC we can live with the temporary solution until #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger.

claudiu.cristea’s picture

Another approach suggested by @catch: making the node types from tests not adding new revisions by default.

Fabianx’s picture

Back to RTBC, looks good to me.

  • catch committed c64a3f7 on 8.3.x
    Issue #2787187 by claudiu.cristea, grahl, azinck, Fabianx, dawehner:...

  • catch committed 0a3c43c on 8.2.x
    Issue #2787187 by claudiu.cristea, grahl, azinck, Fabianx, dawehner:...

  • catch committed 88f89da on 8.1.x
    Issue #2787187 by claudiu.cristea, grahl, azinck, Fabianx, dawehner:...
catch’s picture

Version: 8.2.x-dev » 8.1.x-dev
Status: Reviewed & tested by the community » Fixed

Always fun when there are bugs that cancel each other out.

Committed/pushed to all three 8.x branches, thanks!

Status: Fixed » Closed (fixed)

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

Wim Leers’s picture

Status: Closed (fixed) » Active

This also broke the case of when file A is used in translation X and file B is used in translation Y. When you delete the non-default translation, if that used a different file than the default translation, its usage will never reach zero.

Reopening to ensure a follow-up is created for that.

dawehner’s picture

I don't think though that the non reaching zero problem is a critical issue.

catch’s picture

Priority: Critical » Major
Issue tags: -Triaged D8 critical

Now that #2801777: Give users the option to prevent drupal from automatically marking unused files as temporary is in, this no longer results in unexpected file deletion. #2821423: Dealing with unexpected file deletion due to incorrect file usage is open as a critical meta-issue to discuss the broader approach on this. So I'm going to downgrade this to major after discussion with @xjm and @cilefen, since we feel effort would be better spent on replacing the file_usage system at this point. We can still fix this bug of course as a major.

joseph.olstad’s picture

I encountered issues when relying on file usage data in a cleanup job. I discovered that important files that were still 'in use' were deleted.

There is a related fix/patch that has tests and is passing tests.
see #2810355-61: $entity->isDefaultTranslation() behaves incorrectly when changing default translation, causing file/image field usage to be set to zero, causing files to be deleted

Appreciate community and core maintainers assistance to get this patch to where it needs to be in order for it to be accepted.
Thanks,

Version: 8.1.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Branches prior to 8.8.x are not supported, and Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

catch’s picture

Version: 9.5.x-dev » 8.1.x-dev
Status: Active » Fixed
Issue tags: +Bug Smash Initiative

#47 re-opened this for a follow-up, I think that follow-up is now #3364744: Add a reliable entity-usage system to core so marking fixed again.

Status: Fixed » Closed (fixed)

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