Drupal 9 site has Users and each user has a Paragraph that contains "Phone" data. User => Phone Paragraph connection is made via field $user->field_phone_para.


Somehow database has gotten "ghost" references for the $user->field_phone_para field. When I load the user and print the phone paragraph reference values/targets, it gets 3 responses. In reality there should be only one.

$user = User::load(4049);


array:3 [
  0 => array:2 [
    "target_id" => "8555"
    "target_revision_id" => "15528"
  1 => array:2 [
    "target_id" => "17677"
    "target_revision_id" => "36696"
  2 => array:2 [
    "target_id" => "26289"
    "target_revision_id" => "45308"

user__field_phone_para database table confirms the same - 3 entries for this user.

Yet if I check the paragraph__field_phone database table for those 3 target_id-s , there is entry only for the ID 26289. Which means that 8555 and 17677 are kind of ghosts and should be gone.


What is the correct way to clean up the database from those ghost / orphaned entries?

Ideas / what I've tried

  • Manually saving the user in the Drupal admin removes the ghost references (but not viable due to the amount of users).
  • Just loading the user and then saving the user via save() does not remove the ghost references.
  • Tested https://www.drupal.org/project/entity_reference_purger - does not seem to work with Users + Paragraphs.

Would it make sense to have a SQL query to delete all the entries from the user__field_phone_para database table which don't have corresponding entries in the paragraph__field_phone table? Matching would be done by user__field_phone_para.field_phone_para_target_id and paragraph__field_phone.entity_id.

Only possible issue with deleting directly via the SQL query is that the "delta" would not be reset in the user__field_phone_para table to what it should be - in the current example case it should become 0 for the real entry since we remove 2 ghosts. Yet when new phone number is added via the admin form, Drupal would take care of resetting the delta anyway so probably not an issue.

  • I read this wrong and put in an answer about using the /admin/config/system/delete-orphans feature (which cleans up orphaned entities, the opposite of your problem), but that might still be worth a try. It might also clean up the field references
    – Clive
    Commented Dec 4, 2022 at 22:34
  • @Raido, you are asking how to remove the ghost references. There is probably no existing code because this normally doesn't happen. My guess would be you have contrib or custom code deleting paragraphs instead of deleting field items. Paragraphs are not deleted right away, most times they are used in revisionable entities and you need them in case of reverting to an older revision. For the non-revisionable user entity there could be code trying to do it differently and there you should look for the issue.
    – 4uk4
    Commented Dec 6, 2022 at 7:39

1 Answer 1


What is the correct way to clean up the database from those ghost / orphaned entries?

Use drush errp to clean up orphaned paragraph entities.

Make sure to have a database backup before running the above command.

  • Tested the drush errp and the path that @Clive mentioned. It checked for 47546 paragraphs but did remove only 9 and database still has the ghost entries in the user__field_phone_para table.
    – Raido
    Commented Dec 5, 2022 at 8:50
  • errp is the drush version of that admin page. Seems it only clears up the orphaned entities, not any fields referencing non-existent entities. I think a custom script is the solution here. Use a batch in an update hook, don't use SQL statements, it's never as easy as it looks
    – Clive
    Commented Dec 5, 2022 at 11:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.