Variables injected or set in a Twig file are undefined after the first position of an entity reference field I have a Paragraph setup that has an entity reference field allowing an editor to select multiple nodes to use in a display.

Based on the count of nodes, I want to trigger a class. I figured a way to do this was with hook_preprocess_node() in the theme:

$referringItem = $node-&gt;_referringItem;
    if (!empty($referringItem)) {
      $referringEntity = $referringItem-&gt;getEntity();

      if (
        !empty($referringEntity)
        &amp;&amp; ($referringEntity instanceof NodeInterface || $referringEntity instanceof Paragraph)
       ) {
        $referringEntityType = $referringEntity-&gt;getType();
        $referringEntityTypeId = $referringEntity-&gt;getEntityTypeId();
      }
    }

if ($referringEntityType == 'homepage_feature') {
        $count = $referringEntity-&gt;get('field_items')-&gt;count();

        // Default.
        $variables['top_image'] = FALSE;
        $variables['right_image'] = FALSE;

        // Should this be count is only 1 AND it is the first delta item in field_feature?
        // If not, any single item Homepage Feature will get top-image which may not be
        // desired.
        if ($count == 1) {
          $variables['top_image'] = TRUE;
        }
      }


The logic above might be too involved. Basically I am looking back to see what paragraph type was used, so I can pass new variables to the template.

What I noticed is that even though the code is hit for every node listed, the variables only exist in the first node. I dumped them in the template and it is correct there, but they are undefined in the other nodes.

In Twig, I tried dumping the variable at the top of the template:

{{ top_image }}

I can see it in the first record 1 above the markup, and then it never shows again.

How can I ensure the variables are passed to the template, correctly, every time?

Edit:

Looks like using the same node with the same view mode in different paragraphs or entity references on the same page can cause this to happen.

Is the solution then to add cache tags/context to the node being rendered to account for what parent is outputting it?
Based on the comments to the question, I extended the EntityReferenceEntityFormatter class and modified one part in the viewElements method (the rest is the same):

  $view_builder = $this-&gt;entityTypeManager-&gt;getViewBuilder($entity-&gt;getEntityTypeId());
  $elements[$delta] = $view_builder-&gt;view($entity, $view_mode, $entity-&gt;language()-&gt;getId());

  try {
    $parent = $items-&gt;getParent();
    $parent_entity = $parent-&gt;getValue();
    $elements[$delta]['#cache']['keys'][] = $parent_entity-&gt;id();
    $elements[$delta]['#cache']['keys'][] = $parent_entity-&gt;bundle();
    $elements[$delta]['#cache']['keys'][] = $parent_entity-&gt;getEntityTypeId();
    $elements[$delta]['#cache']['keys'][] = 'context_aware';

    // Add special information for different paragraph types.
    if ($parent_entity-&gt;getEntityTypeId() == 'paragraph') {
      if ($parent_entity-&gt;bundle() == 'homepage_feature') {
        $elements[$delta]['#style_flags']['top_image'] = FALSE;
        $elements[$delta]['#style_flags']['right_image'] = FALSE;

        if ($parent_entity-&gt;get('field_items')-&gt;count() === 1) {
          $elements[$delta]['#style_flags']['top_image'] = TRUE;
        }
      }
    }
  } catch (\Exception $e) {
    // Add logging
  }


Later on, down in preprocess_node:

// ONLY for the homepage handling of featured content.
      if ($referringEntityType == 'homepage_feature') {
        $variables['top_image'] = $variables['elements']['#style_flags']['top_image'];
        $variables['right_image'] = $variables['elements']['#style_flags']['right_image'];
      }


I was able to then add the same node in the same paragraph type multiple times with the correct information. The correct classes are now applied.

Edit: 

Just to add to this too, be sure to set your cacheable dependencies so any change to what holds references will not require a cache clear:

$parent = $items-&gt;getParent();
$entity-&gt;addCacheableDependency($parent);


Edit 2:

Thanks to extra guidance from 4k4, I injected the renderer service and reduced down to:

    $parent = $items-&gt;getParent();
    $parent_entity = $parent-&gt;getValue();
    $elements[$delta]['#cache']['keys'][] = $parent_entity-&gt;id();
    $elements[$delta]['#cache']['keys'][] = $parent_entity-&gt;bundle();
    $elements[$delta]['#cache']['keys'][] = $parent_entity-&gt;getEntityTypeId();
    $elements[$delta]['#cache']['keys'][] = 'context_aware';

    if ($this-&gt;paragraphDisplaySettings-&gt;isApplicable($parent_entity)) {
      $elements[$delta]['#style_flags'] = $this-&gt;paragraphDisplaySettings-&gt;getSettings($parent_entity);
    }

    $this-&gt;renderer-&gt;addCacheableDependency($elements[$delta], $parent);


paragraphDisplaySettings is a custom service object that aids in evaluating different flags to pass through from the original code just to keep it cleaner and leaner. It's working great.