Intercepting not found errors in multi-module applications

Hi all!
I have multi-module app like in 'mvc\multiple-shared-layouts' and have two modules, frontend and backend.
I'm trying to intercept not found events by setting up dispatcher service inside every module's registerServices() method, but it seems application doesn't even run this method.
The idea is to have different not found pages for frontend and backend. How can I achieve it?
Here is example of my Frontend module, backend is the same except 'module' definitions.

Okay, that's clear. But how can I show different 404 pages for different modules? Should I create new module, 'common', where to route all notFound actions and check there what module should run in this case, right?

You don't need new module for that. if You set dispacher on each module.php with custom 404 pages and it's should work. I have similar setup and it's work with different error 404 pages for each module.

When $router->notFound() is defined, it intercepts everything, including /api/ calls and route them to www module error controller.
If I remove $router->notFound(), any call to /api/ is routed to default controller (home page).

I have encountered this because I separate my UI from API and I have different versions for both. However for the api, end users supply an application vendor accept header which defines an api version. Each version is a module. if a that module is not found it throws this error which is caught in the bootstrap try...catch. I can't be sending HTML to api requests and vice versa.

Module 'api_v3' isn't registered in the application container

My api version/module selection logic is in the router service, and in a nest of if conditions i set the default module based on this information. This gets executed before the routes are defined.

I have worked around this by setting my api module to a the latest version of the api if an invalid version is supplied.

$frontend_version = $this->getConfig()->application->frontend_version;
$api_version = $this->getConfig()->application->api_version;
// do some logic on base api route
if (preg_match('/^\/api/', $uri)) {
// if the version string is supplied, process it.
if (preg_match($vendor_regex, $accept, $vendor_version)) {
// check if the version is less than or equal to the latest default api version
if ($vendor_version <= $api_version && $vender_version > 0) {
$api_version = $vendor_version[1];
}
}
// no version matched, or was not supplied
$router->setDefaultModule('api_v' .$api_version);
$router->setDefaultNamespace('App\Api\V' . $api_version . '\Controllers');
} else {
// when not an api request, automatically set frontend to version from config
$router->setDefaultModule('frontend_v' .$frontend_version);
$router->setDefaultNamespace('App\Frontend\V' . $frontend_version . '\Controllers');
}

I push a draft on here https://github.com/phalcon/cphalcon/pull/12746 but I do not have the time to finish it.
What it does is "if module is not found then fire an application:beforeException event". Just in case that someone want to take up the torch.