Two exceptions in src/App/src/Exception/ set an HTTP status that does not match what they represent.
RuntimeException returns 400 Bad Request
RuntimeException::create() sets StatusCodeInterface::STATUS_BAD_REQUEST. Its throw sites are all server-side faults the client had no part in:
Api\App\Template\Renderer — template not found
Api\App\Service\HandlerService — invalid route middleware provided
Api\App\Service\ErrorReportService — missing or invalid ErrorReportServiceInterface config
Api\App\Factory\HandlerDelegatorFactory — HalResponseFactory or ResourceGenerator not registered in the container
A missing template or an unregistered service is a 500, not a 400. As it stands a monitoring rule that alerts on 5xx will never see any of these, and a client gets told it sent a bad request when it did not.
SunsetException returns 401 Unauthorized
SunsetException::create() sets StatusCodeInterface::STATUS_UNAUTHORIZED. It is thrown from one place, Api\App\Attribute\BaseDeprecation::__construct(), when a ResourceDeprecation attribute carries a sunset value that fails Laminas\Validator\Date:
if (null !== $sunset && ! (new Date())->isValid($sunset)) {
throw SunsetException::create(Message::invalidValue(sunset));
}
That is a developer error in an attribute declaration, discovered at attribute construction. It has no authentication dimension, so 401 is misleading — it invites the caller to retry with credentials for something credentials cannot fix. 500 looks right.
Note for whoever fixes this
The v7 documentation previously claimed RuntimeException produced a 500. That has just been corrected to 400 to match the code (dotkernel/api-documentation#170), so changing the status here needs a matching documentation update.
Found while auditing the v7 documentation against 7.0 at commit 45ad282.
Two exceptions in
src/App/src/Exception/set an HTTP status that does not match what they represent.RuntimeExceptionreturns 400 Bad RequestRuntimeException::create()setsStatusCodeInterface::STATUS_BAD_REQUEST. Its throw sites are all server-side faults the client had no part in:Api\App\Template\Renderer— template not foundApi\App\Service\HandlerService— invalid route middleware providedApi\App\Service\ErrorReportService— missing or invalidErrorReportServiceInterfaceconfigApi\App\Factory\HandlerDelegatorFactory—HalResponseFactoryorResourceGeneratornot registered in the containerA missing template or an unregistered service is a
500, not a400. As it stands a monitoring rule that alerts on 5xx will never see any of these, and a client gets told it sent a bad request when it did not.SunsetExceptionreturns 401 UnauthorizedSunsetException::create()setsStatusCodeInterface::STATUS_UNAUTHORIZED. It is thrown from one place,Api\App\Attribute\BaseDeprecation::__construct(), when aResourceDeprecationattribute carries asunsetvalue that failsLaminas\Validator\Date:That is a developer error in an attribute declaration, discovered at attribute construction. It has no authentication dimension, so
401is misleading — it invites the caller to retry with credentials for something credentials cannot fix.500looks right.Note for whoever fixes this
The v7 documentation previously claimed
RuntimeExceptionproduced a500. That has just been corrected to400to match the code (dotkernel/api-documentation#170), so changing the status here needs a matching documentation update.Found while auditing the v7 documentation against
7.0at commit 45ad282.