-
-
Notifications
You must be signed in to change notification settings - Fork 958
Description
API Platform version(s) affected: 4.2.0
Description
I wanted to make additional validation in my custom StateProcessor. When this validation fails I wanted to throw ValidationException to get uniform error response.
I do not need to do additional constraints & extra validators, simple if is enough in my case. That saying I have: throw new ValidationException('error message');.
This results in Fatal error. Error message:
Uncaught TypeError: ApiPlatform\Validator\Exception\ValidationException::getConstraintViolationList(): Return value must be of type Symfony\Component\Validator\ConstraintViolationListInterface, array returned in /app/vendor/api-platform/validator/Exception/ValidationException.php:208
How to reproduce
Throw exception in process method in your custom StateProcessor.
throw new \ApiPlatform\Validator\Exception\ValidationException('custom validation error message');
Possible Solution
$constraintViolationList property is defined as:
private array|ConstraintViolationListInterface $constraintViolationList = [].
| private array|ConstraintViolationListInterface $constraintViolationList = []; |
getConstraintViolationList method is defined as:
public function getConstraintViolationList(): ConstraintViolationListInterface
| public function getConstraintViolationList(): ConstraintViolationListInterface |
Fix 1 proposition
Change method declaration to return also array. This will require to change also in ConstraintViolationListAwareExceptionInterface.
Alternative fix 2 proposition
Change current method from:
public function getConstraintViolationList(): ConstraintViolationListInterface
{
return $this->constraintViolationList;
}To
public function getConstraintViolationList(): ConstraintViolationListInterface
{
if (is_array($this->constraintViolationList)) {
return new ConstraintViolationList();
}
return $this->constraintViolationList;
}Alternative fix 3 proposition
Disallow passing string to $message, because it is misleading in allowed usage?
Additional Context
Stack trace:
#0 /app/vendor/api-platform/symfony/Validator/Serializer/ValidationExceptionNormalizer.php(31): ApiPlatform\Validator\Exception\ValidationException->getConstraintViolationList()
#1 /app/vendor/symfony/serializer/Debug/TraceableNormalizer.php(50): ApiPlatform\Symfony\Validator\Serializer\ValidationExceptionNormalizer->normalize(Object(ApiPlatform\Validator\Exception\ValidationException), 'jsonld', Array)
#2 /app/vendor/symfony/serializer/Serializer.php(152): Symfony\Component\Serializer\Debug\TraceableNormalizer->normalize(Object(ApiPlatform\Validator\Exception\ValidationException), 'jsonld', Array)
#3 /app/vendor/symfony/serializer/Serializer.php(131): Symfony\Component\Serializer\Serializer->normalize(Object(ApiPlatform\Validator\Exception\ValidationException), 'jsonld', Array)
#4 /app/vendor/symfony/serializer/Debug/TraceableSerializer.php(44): Symfony\Component\Serializer\Serializer->serialize(Object(ApiPlatform\Validator\Exception\ValidationException), 'jsonld', Array)
#5 /app/vendor/api-platform/state/Processor/SerializeProcessor.php(85): Symfony\Component\Serializer\Debug\TraceableSerializer->serialize(Object(ApiPlatform\Validator\Exception\ValidationException), 'jsonld', Array)
#6 /app/vendor/api-platform/state/Processor/WriteProcessor.php(54): ApiPlatform\State\Processor\SerializeProcessor->process(Object(ApiPlatform\Validator\Exception\ValidationException), Object(ApiPlatform\Metadata\Error), Array, Array)
#7 /app/vendor/api-platform/symfony/Controller/MainController.php(123): ApiPlatform\State\Processor\WriteProcessor->process(Object(ApiPlatform\Validator\Exception\ValidationException), Object(ApiPlatform\Metadata\Error), Array, Array)
#8 /app/vendor/symfony/http-kernel/HttpKernel.php(183): ApiPlatform\Symfony\Controller\MainController->__invoke(Object(Symfony\Component\HttpFoundation\Request))
#9 /app/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 2)
#10 /app/vendor/symfony/http-kernel/EventListener/ErrorListener.php(99): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 2, false)
#11 /app/vendor/api-platform/symfony/EventListener/ExceptionListener.php(50): Symfony\Component\HttpKernel\EventListener\ErrorListener->onKernelException(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent))
#12 /app/vendor/symfony/event-dispatcher/Debug/WrappedListener.php(115): ApiPlatform\Symfony\EventListener\ExceptionListener->onKernelException(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...', Object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher))
#13 /app/vendor/symfony/event-dispatcher/EventDispatcher.php(206): Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...', Object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher))
#14 /app/vendor/symfony/event-dispatcher/EventDispatcher.php(56): Symfony\Component\EventDispatcher\EventDispatcher->callListeners(Array, 'kernel.exceptio...', Object(Symfony\Component\HttpKernel\Event\ExceptionEvent))
#15 /app/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php(126): Symfony\Component\EventDispatcher\EventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...')
#16 /app/vendor/symfony/http-kernel/HttpKernel.php(241): Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...')
#17 /app/vendor/symfony/http-kernel/HttpKernel.php(91): Symfony\Component\HttpKernel\HttpKernel->handleThrowable(Object(ApiPlatform\Validator\Exception\ValidationException), Object(Symfony\Component\HttpFoundation\Request), 1)
#18 /app/vendor/symfony/http-kernel/Kernel.php(182): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 /app/vendor/runtime/frankenphp-symfony/src/Runner.php(38): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#20 [internal function]: Runtime\FrankenPhpSymfony\Runner->{closure:Runtime\FrankenPhpSymfony\Runner::run():33}()
#21 /app/vendor/runtime/frankenphp-symfony/src/Runner.php(45): frankenphp_handle_request(Object(Closure))
#22 /app/vendor/autoload_runtime.php(29): Runtime\FrankenPhpSymfony\Runner->run()
#23 /app/public/index.php(5): require_once('/app/vendor/aut...')
#24 {main}