From 14287c061e4248ea0121db0ac5ece083140d4986 Mon Sep 17 00:00:00 2001 From: soyuka Date: Sat, 14 Mar 2026 08:26:51 +0100 Subject: [PATCH] fix(validator): initialize detail property in constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit | Q | A | ------------- | --- | Branch? | 4.3 | Tickets | Closes #7843 | License | MIT | Doc PR | ∅ ValidationException::$detail was never set in the constructor, causing an error when getDetail()/getDescription() are called via Error::createFromException(). Initialize it with getMessage() after parent construction. --- src/State/Tests/ErrorProviderTest.php | 17 ++++++++++++++++- src/Validator/Exception/ValidationException.php | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/State/Tests/ErrorProviderTest.php b/src/State/Tests/ErrorProviderTest.php index 7bf1524e67f..22095a5cc8f 100644 --- a/src/State/Tests/ErrorProviderTest.php +++ b/src/State/Tests/ErrorProviderTest.php @@ -14,18 +14,33 @@ namespace ApiPlatform\State\Tests; use ApiPlatform\Metadata\Get; +use ApiPlatform\State\ApiResource\Error; use ApiPlatform\State\ErrorProvider; +use ApiPlatform\Validator\Exception\ValidationException; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Validator\ConstraintViolationList; class ErrorProviderTest extends TestCase { + public function testCreateFromExceptionWithValidationException(): void + { + $violation = new ConstraintViolation('This value is too long.', null, [], null, 'name', 'toolong'); + $exception = new ValidationException(new ConstraintViolationList([$violation])); + $error = Error::createFromException($exception, 422); + + $this->assertSame('An error occurred', $error->getTitle()); + $this->assertSame($exception->getMessage(), $error->getDetail()); + $this->assertSame(422, $error->getStatus()); + } + public function testErrorProviderProduction(): void { $provider = new ErrorProvider(debug: false); $request = Request::create('/'); $request->attributes->set('exception', new \Exception()); - /** @var \ApiPlatform\State\ApiResource\Error */ + /** @var Error */ $error = $provider->provide(new Get(), [], ['request' => $request]); $this->assertEquals('Internal Server Error', $error->getDetail()); } diff --git a/src/Validator/Exception/ValidationException.php b/src/Validator/Exception/ValidationException.php index d8dcef59e13..19a3d129d54 100644 --- a/src/Validator/Exception/ValidationException.php +++ b/src/Validator/Exception/ValidationException.php @@ -111,6 +111,7 @@ public function __construct(string|ConstraintViolationListInterface $message = n if ($message instanceof ConstraintViolationListInterface) { $this->constraintViolationList = $message; parent::__construct($this->__toString(), $code ?? 0, $previous); + $this->detail = $this->getMessage(); return; } @@ -119,6 +120,7 @@ public function __construct(string|ConstraintViolationListInterface $message = n trigger_deprecation('api_platform/core', '5.0', \sprintf('The "%s" exception will have a "%s" first argument in 5.x.', self::class, ConstraintViolationListInterface::class)); parent::__construct($message ?: $this->__toString(), $code ?? 0, $previous); + $this->detail = $this->getMessage(); } public function getId(): string