Problem/Motivation

Turning on the checkbox 'Use field template' in the style section of a view text field causes an exception when viewing the content output:

Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218

Steps to reproduce

1. Add a view page
2. Format -> Show fields
3. Title field -> Style -> Use field template
4. Add a piece of content to basic page.
5. View the view page e.g /test
6. Error occurs

Proposed resolution

TBA

Remaining tasks

Review
Commit

User interface changes

API changes

Data model changes

Release notes snippet

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rviner created an issue. See original summary.

larowlan’s picture

Status: Active » Postponed (maintainer needs more info)
Issue tags: +Bug Smash Initiative, +Needs steps to reproduce

Can you share the config of your view and some steps to reproduce?

Thanks

rviner’s picture

Sure, this also happens on a plain vanilla Drupal 9.3 site. The error didn't occur in 9.2. Here is the view.

1. Add a view page
2. Format -> Show fields
3. Title field -> Style -> Use field template
4. Add a piece of content to basic page.
5. View the view page e.g /test
6. Error occurs

uuid: c1b1b6df-3b6d-4f2e-acf7-e3d95e4cb923
langcode: en
status: true
dependencies:
  module:
    - node
    - user
id: test
label: test
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
display:
  default:
    id: default
    display_title: Default
    display_plugin: default
    position: 0
    display_options:
      title: test
      fields:
        title:
          id: title
          table: node_field_data
          field: title
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: title
          plugin_id: field
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: false
            ellipsis: false
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          click_sort_column: value
          type: string
          settings:
            link_to_entity: true
          group_column: value
          group_columns: {  }
          group_rows: true
          delta_limit: 0
          delta_offset: 0
          delta_reversed: false
          delta_first_last: false
          multi_type: separator
          separator: ', '
          field_api_classes: true
      pager:
        type: mini
        options:
          offset: 0
          items_per_page: 10
          total_pages: null
          id: 0
          tags:
            next: ››
            previous: ‹‹
          expose:
            items_per_page: false
            items_per_page_label: 'Items per page'
            items_per_page_options: '5, 10, 25, 50'
            items_per_page_options_all: false
            items_per_page_options_all_label: '- All -'
            offset: false
            offset_label: Offset
      exposed_form:
        type: basic
        options:
          submit_button: Apply
          reset_button: false
          reset_button_label: Reset
          exposed_sorts_label: 'Sort by'
          expose_sort_order: true
          sort_asc_label: Asc
          sort_desc_label: Desc
      access:
        type: perm
        options:
          perm: 'access content'
      cache:
        type: tag
        options: {  }
      empty: {  }
      sorts:
        created:
          id: created
          table: node_field_data
          field: created
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: created
          plugin_id: date
          order: DESC
          expose:
            label: ''
            field_identifier: ''
          exposed: false
          granularity: second
      arguments: {  }
      filters:
        status:
          id: status
          table: node_field_data
          field: status
          entity_type: node
          entity_field: status
          plugin_id: boolean
          value: '1'
          group: 1
          expose:
            operator: ''
            operator_limit_selection: false
            operator_list: {  }
      style:
        type: default
      row:
        type: fields
        options:
          default_field_elements: true
          inline: {  }
          separator: ''
          hide_empty: false
      query:
        type: views_query
        options:
          query_comment: ''
          disable_sql_rewrite: false
          distinct: false
          replica: false
          query_tags: {  }
      relationships: {  }
      header: {  }
      footer: {  }
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url.query_args
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
  page_1:
    id: page_1
    display_title: Page
    display_plugin: page
    position: 1
    display_options:
      display_extenders: {  }
      path: test
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url.query_args
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
rviner’s picture

Status: Postponed (maintainer needs more info) » Active
larowlan’s picture

Thanks, that's very helpful

Spokje’s picture

Version: 9.3.x-dev » 9.4.x-dev
Issue tags: +Needs tests
FileSize
608 bytes

Confirmed this happening with the attached view config from #3 (like @larowlan already said: Super helpful, thanks!).

This looks like a regression introduced in #2794261: Deprecate render() function in common.inc:

\Drupal\views\Plugin\views\field\EntityField::render_item originally used the render function from core/includes/common.inc.

That function has a check if the provided element to be rendered is not an array, in which case it returns the element as-is. (See https://git.drupalcode.org/project/drupal/-/blob/9.3.x/core/includes/common.inc#L406-410)

That check seems to be missing from the currently used \Drupal\Core\Render\Renderer::render.
If I add that check and return the element as-is in \Drupal\Core\Render\Renderer::doRender as in the attached patch, the test View works without errors.

Upping version to 9.4.x-dev since changes need to be committed there first and then be backported
Tagging with Needs tests for a minimal testcase that proves the above is indeed true.

It would be nice if anybody that ran into this issue can confirm the patch does make the error go away.

Spokje’s picture

Status: Active » Needs work
Related issues: +#2794261: Deprecate render() function in common.inc
GNUMatrix’s picture

I ran into this issue today after installing 9.3. This fixed it, thanks very much!

Spokje’s picture

FileSize
662 bytes

Like this approach better, seems to be tackling the root cause of the problem.

No interdiff since it's a new approach.

rviner’s picture

I can confirm this fixes the error.

However it doesn't actually use the field template anymore which it used to.

catch’s picture

Priority: Major » Critical

Bumping to critical.

Spokje’s picture

Priority: Critical » Major
Issue tags: -Needs tests
FileSize
6.51 KB
Spokje’s picture

Priority: Major » Critical
Spokje’s picture

This patch is a combination of patch #6 (patch #9 doesn't respect the field template) with the addition of a test class.

Spokje’s picture

I can confirm this fixes the error.

However it doesn't actually use the field template anymore which it used to.

Thus spoketh @rviner in #10

I ran the test_only patch from #12 against a clean install of 9.2.x-dev and it passed.

What does your field template look like and are you sure the classes in there aren't applied to the View after patching it?
I would expect my test-class to fail if the field template wasn't applied, since it's actively looking for classes inherited from the field template in the theme (which is classy in the test-class).

rviner’s picture

Ok, it works with the latest patch.

It didn't work with patch from #9. #9 fixes the error but doesn't use the template.

Spokje’s picture

Spokje’s picture

Spokje’s picture

Ok, it works with the latest patch.

It didn't work with patch from #9. #9 fixes the error but doesn't use the template.

Thus spoketh @rviner in #16

Great, thanks for the confirmation :)

Spokje’s picture

FileSize
1.33 KB

Interdiff for the archaeologists out there.

Spokje’s picture

Status: Needs work » Needs review

TestBot is going to return green AFAICS, now it's time to appease the Big Brains around here by putting this up for scrutiny => Needs review.

MrDaleSmith’s picture

Confirmed https://www.drupal.org/project/drupal/issues/3253568#comment-14335441 fixes the issue and uses the correct template in Drupal 9.3

quietone’s picture

Issue summary: View changes
paul121’s picture

Can also confirm that the fix in #6 solves the error and uses the correct template.

Attached is a simpler kernel test for this

paul121’s picture

Oops. I meant for the test to use the existing test_field_field_test view, not test_field_alias_test. Not a big difference but this might be better.

And just for reference - I got this approach from FieldWebTest::testFieldClasses().

The last submitted patch, 24: 323568-24-test-only.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 25: 323568-25-test-only.patch, failed testing. View results

Spokje’s picture

Status: Needs work » Needs review
alexpott’s picture

I'm guessing that this error is happening because a call to render() has been replaced with \Drupal::service('renderer')->render(); as render() has been deprecated in 9.3.x.

The change made here is quite a big change and I'm not sure we're basically repeating the following code from render()...

    // Safe-guard for inappropriate use of render() on flat variables: return
    // the variable as-is.
    return $element;

Without the comment.

In someways this feels a step backwards. Why are we not fixing this in views?

alexpott’s picture

Status: Needs review » Needs work

Yep this was caused by #2794261: Deprecate render() function in common.inc.

One option would be to move some of the logic from render to \Drupal\views\Plugin\views\field\EntityField::render_item()... but that leaves the double rendering in place.

The correct fix is to change \Drupal\views\Plugin\views\field\EntityField::getItems() from

    if ($this->options['field_api_classes']) {
      return [['rendered' => $this->renderer->render($build_list)]];
    }

to

    if ($this->options['field_api_classes']) {
      return [['rendered' => $build_list]];
    }

And rely on the rendering occurring in \Drupal\views\Plugin\views\field\FieldPluginBase::advancedRender()

However that's tricky because we'd be changing what's returned from a public method... although it'd then be more similar to what is returned when field_api_classes is not checked...

Not sure what to do here but I'm pretty sure that the change to the renderer service is not the best option.

longwave’s picture

I think the suggested fix in #30 is the right way forward.

If the checkbox is not checked then each delta is extracted separately and rendered to avoid the field API wrapper:

      $items[$delta] = [
        'rendered' => $build_list[$delta],
      ];

So by returning the full render array when the field template is enabled we are making this more consistent.

The docblock also says:

   * @return array
   *   An array of items for the field.

And while that's not very specific about what the "items" are, at least we would be returning an array of items rather than a pre-rendered string.

Spokje’s picture

Status: Needs work » Needs review

The fix in #30 works, according to #31 we can get away with it due to the non-specific doc-block.

longwave’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

This is going to need a test - as far as I can see we don't have any test views that use field_api_classes: true.

Spokje’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

This is going to need a test - as far as I can see we don't have any test views that use field_api_classes: true.

I believe the test is already in the patch?

+++ b/core/modules/views/tests/src/Kernel/Handler/FieldFieldTest.php
@@ -339,6 +339,27 @@ public function testFieldAliasRender() {
     }
   }
 
+  /**
+   * Tests the result of a view field with field_api_classes enabled.
+   */
+  public function testFieldApiClassesRender() {
+    /** @var \Drupal\Core\Render\RendererInterface $renderer */
+    $renderer = $this->container->get('renderer');
+    $executable = Views::getView('test_field_field_test');
+    $executable->initHandlers();
+
+    // Enable field_api_classes for the id field.
+    $id_field = $executable->field['id'];
+    $id_field->options['field_api_classes'] = TRUE;
+
+    // Test that the ID field renders with multiple divs from field template.
+    $output = $executable->preview();
+    $output = $renderer->renderRoot($output);
+    $this->setRawContent($output);
+    $field_values = $this->xpath('//div[contains(@class, "views-field-id")]/span[contains(@class, :class)]/div', [':class' => 'field-content']);
+    $this->assertNotEmpty($field_values);
+  }
longwave’s picture

Status: Needs review » Reviewed & tested by the community

Oops, I think only read the interdiff and then went looking for an exported view after applying the patch locally :)

catch’s picture

I think #32 is probably OK, the only way it could break is if a custom module is doing something very specific to this views configuration - like a view-specific alter. Since that's not impossible, we should add a change record and a release note, but it seems unlikely so probably OK for this to go into 9.3.1.

The other option would doing the earlier approach in 9.3 and this approach in 9.4.

tonytheferg’s picture

Title: Error when checkbox 'Use field template' is checked » Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218 of /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php) when checkbox 'Use field template' is checked

+ 1 for RTBC.

I put the error in the title for SEO results as I searched the error multiple times, but had to come to the release page to find the bug.

tonytheferg’s picture

Title: Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218 of /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php) when checkbox 'Use field template' is checked » Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked
Spokje’s picture

Title: Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked » Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked

  • catch committed bd9fa27 on 10.0.x
    Issue #3253568 by Spokje, paul121, rviner, longwave, alexpott, quietone...

  • catch committed 4f3749b on 9.4.x
    Issue #3253568 by Spokje, paul121, rviner, longwave, alexpott, quietone...

  • catch committed 698e3a8 on 9.3.x
    Issue #3253568 by Spokje, paul121, rviner, longwave, alexpott, quietone...
catch’s picture

Version: 9.4.x-dev » 9.3.x-dev
Issue summary: View changes
Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs release note, -Needs change record

I've added a release note, I couldn't think of anything to put in the change record that's not in the release note, and the likelihood of this causing an issue is close to zero. Additionally for sites already on 9.3.0 they have a fatal error on these views so it can't possibly be worse than that.

Committed/pushed to 10.0.x and cherry-picked to 9.4.x and 9.3.x, thanks!

Spokje’s picture

Version: 9.3.x-dev » 9.4.x-dev
Status: Fixed » Reviewed & tested by the community
Issue tags: +9.3.1 release notes
Spokje’s picture

Version: 9.4.x-dev » 9.3.x-dev
Status: Reviewed & tested by the community » Fixed

Restoring meta-data

eahonet’s picture

Title: Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked » Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked
Version: 9.3.x-dev » 9.4.x-dev
Issue summary: View changes
Status: Fixed » Reviewed & tested by the community
Issue tags: -9.3.1 release notes +Needs release note, +Needs change record

Thank you! #32 patch solve the issue for the website I was updating.

Spokje’s picture

Title: Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked » Error: Cannot use object of type Drupal\Core\Render\Markup as array in Drupal\Core\Render\Renderer->doRender() (line 218. When checkbox 'Use field template' is checked
Version: 9.4.x-dev » 9.3.x-dev
Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs release note, -Needs change record +9.3.1 release notes

Re-Restoring meta-data.

mefron’s picture

I wanted to mention: I have a view that is, I believe, suffering from either this bug or a similar one. However, none of the fields in this view use the field template option.

I have isolated the problem to a particular view on my site, which begins to fail when I upgraded from d9.2.10 to 9.3.0. As I mentioned, none of the fields in the view use the field template option. As such, applying the suggested patch doesn't resolve the exception I'm seeing when I try to load a page that contains the view.

The exception looks like so:
2021/12/17 16:03:36 [error] 1674#1674: *260 FastCGI sent in stderr: "PHP message: Uncaught PHP Exception Twig\Error\RuntimeError: "The "replace" filter expects an array or "Traversable" as replace values, got "string"

== added later ==
I have tracked down where the problem is in my application. In the view setup/admin page, under "format" I have specified an Unformatted List showing Fields. On the settings for the unformatted list, I've specified the "row class" as: {{ type|replace(' ', '-')|lower }} . This seems to be the thing that is causing the exception.

I'm not expert enough to know if this is the same problem described in this thread. But it definitely arose when I upgraded to D9.3.0.

hockey2112’s picture

#6 worked for me.

catch’s picture

@mefron you can try applying the patch here to your site, or updating to 9.3.x dev. If that doesn't resolve your issue, please open a new issue in this queue with the information you provided so far (but ideally steps to reproduce the bug from a clean Drupal install - such as recreating the view configuration).

Spokje’s picture

@mefron I've stumbled over this stack overflow link https://stackoverflow.com/a/54895016 which isn't Drupal related, but might help.

If not: You should follow the advice of @catch and open a new issue.

PiRoth’s picture

The patch from spokje works for me.

Many thx!!!!

Status: Fixed » Closed (fixed)

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

stefvanlooveren’s picture

whoa. Thanks for the patch. This caused some big unnotified error on a D9.4 project.