Exception handling is a little bit different to handling 404's - To create a 404, we can just pop a middleware in the pipe before the standard Mezzio handler and fall back to that if a CMS 404 cannot be generated.
For exceptions, we wrap the default error response generator with our own by way of a delegator factory and attempt to resolve the correct document, falling back to the default Mezzio error response generator when this is not possible. There's an additional check here for development mode flags, so that in development, you will still see Whoops errors.
The app has the concept of a default error page and then more specific errors based on HTTP status, or exception code - this is super handy for authorisation or authentication errors but simple enough if all you need is a single 'error' page.
As with 404's the default error and each error mapped to a specific code must be 'Document Locators' that can be retrieved from the DI container.
The following snippet describes a setup where 500 errors and any other exceptional situation will present a default error page and a specific error page for 403 errors…
<?php use App\Content\Container\SingleDocumentLocatorStaticFactory; return [ 'primo' => [ 'documents' => [ 'document.500' => [ 'predicates' => [ Predicate::at('document.type', 'error'), Predicate::at('my.error.errorCode', 500), ], ], 'document.403' => [ 'predicates' => [ Predicate::at('document.type', 'error'), Predicate::at('my.error.errorCode', 403), ], ], ], 'error' => [ 'default' => 'document.500', 'map' => [ 403 => 'document.403', ], ], ], 'dependencies' => [ 'factories' => [ 'document.500' => [SingleDocumentLocatorStaticFactory::class, 'document.500'], 'document.403' => [SingleDocumentLocatorStaticFactory::class, 'document.403'], ], ], ];