Argument #1 ($rpc_responses) must be of type array, null given

Created on 13 June 2022, over 2 years ago
Updated 13 April 2024, 9 months ago

Problem/Motivation

When attempting to use this module with PHP 8.1 and a custom endpoint, I'm getting the following error:

TypeError: Drupal\jsonrpc\Controller\HttpController::aggregateResponseHeaders(): Argument #1 ($rpc_responses) must be of type array, null given, called in /app/web/modules/contrib/jsonrpc/src/Controller/HttpController.php on line 133 in Drupal\jsonrpc\Controller\HttpController->aggregateResponseHeaders() (line 303 of modules/contrib/jsonrpc/src/Controller/HttpController.php).

Steps to reproduce

Here's my Method **CancelUserAccount.php**:

<?php

namespace Drupal\mymodule\Plugin\jsonrpc\Method;

use Drupal\Core\Logger\LoggerChannelFactory;
use Drupal\Core\Session\AccountInterface;
use Drupal\jsonrpc\MethodInterface;
use Drupal\jsonrpc\Object\ParameterBag;
use Drupal\jsonrpc\Plugin\JsonRpcMethodBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a way for the logged-in use to cancel the user's account.
 *
 * @JsonRpcMethod(
 *   id = "user.cancel",
 *   usage = @Translation("Cancels the logged-in user's account."),
 *   access = {"cancel account"},
 * ),
 */
class CancelUserAccount extends JsonRpcMethodBase {

  /**
   * {@inheritdoc}
   */
  public function execute(ParameterBag $params) {
    $uid = $this->currentUser->id();
    // Make sure that we do not try to cancel user 1 or anonymous.
    if ($uid !== 1 && $uid !== 0) {
      $user_storage = \Drupal::entityTypeManager()->getStorage('user');
      // $user_storage = $this->entityTypeManager->getStorage('user');
      $current_user = $user_storage->load($uid);
      // See: https://drupal.stackexchange.com/a/204422.
      // Send the user the "account blocked" confirmation email.
      _user_mail_notify('status_blocked', $current_user);
      $current_user->set('status', FALSE);
      $current_user->save();
      $this->loggerFactory->notice("User account for UID @uid cancelled by JSON RPC.", [
        '@uid' => $current_user->id(),
      ]);
      return TRUE;
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public static function outputSchema() {
    return NULL;
    // return ['type' => 'string'];
  }

  /**
   * The current user account.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected AccountInterface $currentUser;

  /**
   * Logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactory
   */
  protected $loggerFactory;

  /**
   * Constructs a new EntityResourceBase object.
   *
   * @param array $configuration
   *   JSON-RPC config.
   * @param string $plugin_id
   *   The plugin ID.
   * @param \Drupal\jsonrpc\MethodInterface $plugin_definition
   *   The plugin definition.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The current user.
   * @param \Drupal\Core\Logger\LoggerChannelFactory $logger_factory
   *   The Watchdog logger.
   */
  public function __construct(array $configuration, string $plugin_id, MethodInterface $plugin_definition, AccountInterface $account, LoggerChannelFactory $logger_factory) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->currentUser = $account;
    $this->loggerFactory = $logger_factory->get('mymodule');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration, $plugin_id, $plugin_definition,
      $container->get('current_user'),
      $container->get('logger.factory'),
    );
  }

}

Proposed resolution

In HttpController.php:

    try {
      $rpc_responses = $this->getRpcResponses($rpc_requests);

      // Aggregate the response headers so we can add them to the HTTP response.
      $header_bag = $this->aggregateResponseHeaders($rpc_responses);

      // If no RPC response(s) were generated (happens if all of the request(s)
      // were notifications), then return a 204 HTTP response.
      if (empty($rpc_responses)) {
        $response = CacheableJsonResponse::create(NULL, Response::HTTP_NO_CONTENT);
        $response->headers->add($header_bag->all());
        return $response;
      }

The problem here is that getRpcResponses() returns Response[]|null, but aggregateResponseHeaders() has an array typehint, so if getRpcResponses returns null, then the error occurs.

I'm not sure how to fix this though because if $rpc_responses is NULL, then it needs $header_bag in the if (empty($rpc_responses)), but $header_bag hasn't been generated because $rpc_responses is null.

Remaining tasks

User interface changes

API changes

Data model changes

๐Ÿ› Bug report
Status

Needs review

Version

2.0

Component

Code

Created by

๐Ÿ‡ฏ๐Ÿ‡ตJapan ptmkenny

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.2.1 + Environment: PHP 8.1 & MariaDB 10.3.22
    last update 9 months ago
    4 pass
  • @ptmkenny opened merge request.
  • ๐Ÿ‡ฏ๐Ÿ‡ตJapan ptmkenny

    Added an MR to hopefully make this easier to fix.

  • Status changed to Closed: outdated 5 months ago
  • ๐Ÿ‡ฏ๐Ÿ‡ตJapan ptmkenny

    It looks like this was fixed by some of the other changes I committed today, so I'm closing this.

  • ๐Ÿ‡จ๐Ÿ‡พCyprus alex.bukach

    alex.bukach โ†’ made their first commit to this issueโ€™s fork.

  • ๐Ÿ‡จ๐Ÿ‡พCyprus alex.bukach

    @ptmkenny no, it does not look like you addressed in 2.x so it remains relevant. I rebased your MR against the head of 2.x.

  • ๐Ÿ‡ฏ๐Ÿ‡ตJapan ptmkenny

    Thanks for updating this. "Needs work" as tests are failing. Also, can you provide steps to reproduce this? I tried to reproduce it but failed, which is why I closed the issue in #5.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia chhavi.sharma

    Can you please specify which tests are failing? According to MR, only the phpcs pipeline is failing. Do we need to clear that only or is there something else?

  • ๐Ÿ‡ฏ๐Ÿ‡ตJapan ptmkenny

    @cchavi.sharma phpcs needs to be fixed, but much more important is documenting a way to reproduce this issue. We may add an additional unit test to make sure we don't break this again in the future.

  • ๐Ÿ‡ฏ๐Ÿ‡ตJapan ptmkenny

    This morning, I attempted to reproduce this again but could not. I tried using the same endpoint that I described in the issue summary, but the error no longer occurs for me.

    So before I commit a fix for this, I need an example of when this is failing. It may be that the fix here is just covering another error where we should be throwing an exception instead.

Production build 0.71.5 2024