Crash when method with optional description specified for a parameter is called

Created on 10 September 2024, 4 months ago
Updated 11 September 2024, 4 months ago

Problem/Motivation

Since version 2.1.0 the "jsonrpc/methods" call crashes, as well as the methods themselves.

This is probably due to the change in https://www.drupal.org/project/jsonrpc/issues/3471816 🐛 Fix incorrect PHPDoc type hints Fixed

My methods *do* specify the (optional) description, and this is the error I get now:

[Type Error] Attribute \"description\" of @JsonRpcParameterDefinition declared on class Drupal\\my_module\\Plugin\\jsonrpc\\Method\\CheckExpoTokenApi expects a(n) \\Drupal\\Core\\Annotation\\Translation|null, but got an instance of Drupal\\Core\\Annotation\\Translation.

Here is the annotation:

 * @JsonRpcMethod(
 *     id="my_module.checkExpoTokenApi",
 *     usage=@Translation("Check expo token exists"),
 *     params={
 *         "expo_token": @JsonRpcParameterDefinition(
 *             schema={"type": "string"},
 *             required=true,
 *             description=@Translation("The expo device token.")
 *         ),
 *     }
 * ),

If I *remove* the description altogether then the check complains about the next method.
Downgrading to 2.0.6 makes everything work again.

Steps to reproduce

Create a JSON-RPC method with a description and request jsonrpc/methods.

🐛 Bug report
Status

Fixed

Version

2.1

Component

Code

Created by

🇩🇪Germany cspitzlay 🇩🇪🇪🇺

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

Merge Requests

Comments & Activities

  • Issue created by @cspitzlay
  • First commit to issue fork.
  • 🇯🇵Japan ptmkenny

    Thank you for reporting this, and I'm sorry that the update broke JSON-RPC for you. It seems that none of the methods in jsonrpc_core set the description, so this was missing from the test coverage. I'll try to fix this today and then, after you confirm the fix is working for you, make a new release.

  • Merge request !32Fix crash due to description → (Merged) created by ptmkenny
  • Status changed to Needs review 4 months ago
  • 🇯🇵Japan ptmkenny

    MR31 is for 2.x, MR 32 is for 3.x.

    Please test MR31 and let me know if this fixes the issue for you.

  • 🇩🇪Germany cspitzlay 🇩🇪🇪🇺

    I tested MR31 and it solves the issue for me.

    • The methods that crashed with 2.1.0 work with the change. So I guess it adresses the issue correctly.
    • The jsonrpc/methods route now gives me a different error, though. See below
    The website encountered an unexpected error. Try again later.<br><br><em
            class="placeholder">Error</em>: Call to a member function normalize() on null in <em class="placeholder">Drupal\jsonrpc_discovery\Normalizer\AnnotationNormalizer-&gt;normalize()</em> (line
    <em class="placeholder">63</em> of <em class="placeholder">modules/contrib/jsonrpc/modules/jsonrpc_discovery/src/Normalizer/AnnotationNormalizer.php</em>).
    <pre class="backtrace">Symfony\Component\Serializer\Serializer-&gt;normalize(Object, &#039;json&#039;, Array) (Line: 177)
    Symfony\Component\Serializer\Serializer-&gt;normalize(Array, &#039;json&#039;, Array) (Line: 177)
    Symfony\Component\Serializer\Serializer-&gt;normalize(Array, &#039;json&#039;, Array) (Line: 138)
    Symfony\Component\Serializer\Serializer-&gt;serialize(Array, &#039;json&#039;, Array) (Line: 67)
    Drupal\jsonrpc_discovery\Controller\DiscoveryController-&gt;methods()
    call_user_func_array(Array, Array) (Line: 123)
    

    I am not sure this is a bug in the module or a wrong method annotation.
    I'll try to find out.

  • 🇩🇪Germany cspitzlay 🇩🇪🇪🇺

    Ok, so in the debugger I see that it crashes right at the first JSON-RPC method, the one in the issue summary.

     public function normalize($object, $format = NULL, array $context = []): array|\ArrayObject|bool|float|int|string|null {
        $attributes = [];
        foreach ($object as $key => $value) {
          switch ($key) {
            case 'id':
            case 'call':
            case 'access':
              break;
    
            default:
              $child = $value instanceof AnnotationInterface ? $value->get() : $value;
              if (isset($context[static::DEPTH_KEY]) && $child instanceof AnnotationInterface || (is_array($child)) && Inspector::assertAllObjects($child, AnnotationInterface::class)) {
                if ($context[static::DEPTH_KEY] === 0) {
                  break;
                }
                $context[static::DEPTH_KEY] -= 1;
              }
    --->    $attributes[$key] = $this->normalizer->normalize($child, $format, $context);
          }
        }
     

    The key is 'output' at that time and $this->normalizer is NULL.

    There is no mention of output in my method's annotation,
    but IIRC the result of the output() method is set dynamically at some point
    so the structure of the output appears in the method's self-documentation.

  • 🇩🇪Germany cspitzlay 🇩🇪🇪🇺

    Found the spot: In \Drupal\jsonrpc\Plugin\JsonRpcMethodManager::alterDefinitions, there's

          $class = $method->getClass();
          $output_schema = $class::outputSchema();
          $method->output = $output_schema;
    
  • 🇯🇵Japan ptmkenny

    Thank you for debugging further.

    Yes, please create a separate issue. Since this fixes the first problem (and adds a description to one of the tests to make sure it won't happen again), I'll go ahead and commit this, and then we can work on the other issue.

  • Pipeline finished with Skipped
    4 months ago
    #279997
    • ptmkenny committed f4249889 on 2.x
      Issue #3473362 by ptmkenny, cspitzlay: Crash when method with optional...
  • Pipeline finished with Skipped
    4 months ago
    #279999
  • Pipeline finished with Skipped
    4 months ago
    #280001
    • ptmkenny committed 2334d024 on 3.x
      Issue #3473362 by ptmkenny, cspitzlay: Crash when method with optional...
  • Status changed to Fixed 4 months ago
  • 🇩🇪Germany cspitzlay 🇩🇪🇪🇺

    Here is the issue for the other crash: 🐛 Crash on jsonrpc/methods route Active

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

Production build 0.71.5 2024