0

When POSTing to JSON:API with invalid parameters, UnprocessableHttpEntityException is thrown.

However, in the logs, this exception does not contain the invalid payload that caused the exception. How can I log the bad payload with the exception?

In a custom module, I created MymoduleExceptionSubscriber.php::

namespace Drupal\mymodule\EventSubscriber;

class MymoduleExceptionSubscriber implements EventSubscriberInterface {   
  public function onException(ExceptionEvent $event): void {
    $exception = $event
      ->getThrowable();
    $original_exception = $this->getOriginalException($exception);

    if ($original_exception instanceof UnprocessableHttpEntityException) {
        $this->logger->get('custom_jsonapi_exception')->error($this->getErrorMessage($original_exception));
      }
  }

  /**
   * Generate a useful error message to log an exception.
   *
   * @param \Exception $exception
   *   The exception to generate an error message for.
   *
   * @return string
   *   The generated error message.
   */
  private function getErrorMessage(\Exception $exception): string {
    $exception_class = get_class($exception);
    $violations = '';
    if(method_exists($exception, 'getViolations')) {
      $violations = '<br>Violations' . $exception->getViolations();
    }
    return "Class: $exception_class <br>Message: " .
      $exception->getMessage() .
      $violations .
      '<br>File: ' .
      $exception->getFile() .
      '<br>Line number: ' .
      $exception->getLine() .
      '<br>Stack trace:<br>' .
      $exception->getTraceAsString();
  }

  /**
   * Drupal may catch exceptions for us and rethrow them. This undoes that.
   *
   * More info: https://drupal.stackexchange.com/a/311935.
   *
   * @param \Throwable $exception
   *   The exception to drill into.
   *
   * @return \Throwable
   *   The original (first) exception.
   */
  private function getOriginalException(\Throwable $exception): \Throwable {
    $original_exception = $exception;
    while ($original_exception->getPrevious()) {
      $original_exception = $original_exception->getPrevious();
    }
    return $original_exception;
  }

}

This allows me to catch the exception and, by logging getViolations(), get information on which field(s) caused the UnprocessableHttpEntityException. However, knowing which fields failed to validate is only half the problem-- the other half is checking what the bad input in the payload was.

How can I log such info?

1 Answer 1

1

For the payload get the request referenced in the event:

$request = $event->getRequest();
$body = Json::decode($request->getContent());
$data = $body['data'];

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.