Problem/Motivation

The ChecklistapiRoutes::routes() function is triggered on router rebuild, calling
checklistapi_get_checklist_info().

The hook_checklistapi_checklist_info() definition states that the #url param of an item
should be passed as a \Drupal\Core\Url object.

The usage of Url::fromUri() on an internal path in an hook_checklistapi_checklist_info() implementation leads to a recursive router rebuild exception when called by ChecklistapiRoutes::routes().

This scenario occurs in:

#2844672: "RuntimeException: Recursive router rebuild detected" after module enabled
#2853459: "Recursive router rebuild detected" during installation of the module with a profile
#2904413: Enabling content translation module results in RuntimeException

#2901338: RuntimeException "Recursive router rebuild detected.": race conditions may also be related.

Proposed resolution

I would suggest mitigating this issue by implementing separate hook definitions:

hook_checklistapi_checklist_routes()

hook_checklistapi_checklist_info()

Using a parameter would also be reasonable, I assume.

hook_checklistapi_checklist_info($routes_only)

Remaining tasks

User interface changes

API changes

Data model changes

Original report by [username]

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

volkerk created an issue. See original summary.

TravisCarden’s picture

Thanks for the report, @volkerk. Let me think a little about how I to handle this with the least disruption to consumers.

TravisCarden’s picture

Issue summary: View changes
volkerk’s picture

Hi Travis,

I guess the approach using a parameter would be the least disruptive. Existing modules using the Checklist API will still be able to function, people encountering above mentioned issues and new modules could just implement the parameter.

Maybe there is another way to achieve this, either way I would be happy to help with the implementation.

TravisCarden’s picture

Okay, @volkerk, I've had a little time to think about this. I think the best long-term solution to this problem is to modernize the architecture of the API in general, making checklists entities whose metadata is defined separately from their checklist items. But that's a major version upgrade kind of change, and I don't have any free time to spend on this module at present. So in lieu of that, I'd like to add an optional #callback item to hook_checklistapi_checklist_info() to specify a callable for returning form groups and items separately rather than inline. The inline definition can be deprecated support for it can be retained to maintain backwards compatibility. We'll just say that you provide one or the other, and #callback will take precedent if you provide both. This approach provides a complete solution for modules that experience the problem, and other modules will be unaffected. I would most gladly accept your help with the implementation, since as I said above I have no free time for this at the moment; thanks for the offer! If you can write a patch that keeps the tests passing I'll review it!

TravisCarden’s picture

Title: RuntimeException: Recursive router rebuild detected » Url objects in hook_checklistapi_checklist_info cause RuntimeException: Recursive router rebuild detected
TravisCarden’s picture

Title: Url objects in hook_checklistapi_checklist_info cause RuntimeException: Recursive router rebuild detected » Url objects in hook_checklistapi_checklist_info() cause RuntimeException: Recursive router rebuild detected
chr.fritsch’s picture

Status: Active » Needs review
FileSize
1.67 KB

Here is the patch to introduce the #callback key

chr.fritsch’s picture

Add a !empty check

TravisCarden’s picture

Status: Needs review » Fixed

Nice, @chr.fritsch; thanks! Committed with minor modification. I've rolled a new module release containing this enhancement. Enjoy!

chr.fritsch’s picture

Status: Fixed » Needs work

Your additional changes in checklistapi_get_checklist_info() break everything again. Now there is now difference to the behavior before. It's not allowed to retrieve the items in checklistapi_get_checklist_info, because of "Recursive router exception"

TravisCarden’s picture

Status: Needs work » Needs review
FileSize
645 bytes

Hmm. I can't reproduce the recursive router exception, @chr.fritsch, but what you're saying makes sense logically. Does the attached patch fix it for you?

chr.fritsch’s picture

You can reproduce it, by enabling content_translation module.

With your patch from #13 it works fine. I updated it a bit, because the additional checklistapi_add_checklist_items() calls are not needed when we call it in checklistapi_get_checklist_info().

TravisCarden’s picture

Status: Needs review » Fixed

All right, @chr.fritsch; committed. I cut a new release for the fix. Sorry for the confusion, and thanks for the help!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

AswathyAjish’s picture

I got the following error when installed "Checklist API" module with a profile :

The website encountered an unexpected error. Please try again later.
RuntimeException: Recursive router rebuild detected. in Drupal\Core\Routing\RouteBuilder->rebuild() (line 121 of core/lib/Drupal/Core/Routing/RouteBuilder.php).

Drupal\Core\Routing\RouteBuilder->rebuild() (Line: 83)
Drupal\Core\ProxyClass\Routing\RouteBuilder->rebuild() (Line: 55)
Drupal\Core\Routing\RouteProviderLazyBuilder->getRouteProvider() (Line: 72)
Drupal\Core\Routing\RouteProviderLazyBuilder->getRouteByName('checklistapi.checklists.seo_checklist') (Line: 915)
_seo_checklist_preprocess_checklist_info(Array) (Line: 803)
seo_checklist_checklistapi_checklist_info()
call_user_func_array('seo_checklist_checklistapi_checklist_info', Array) (Line: 402)
Drupal\Core\Extension\ModuleHandler->invokeAll('checklistapi_checklist_info') (Line: 20)
Drupal\checklistapi\Routing\ChecklistapiRoutes->routes()
call_user_func(Array) (Line: 146)
Drupal\Core\Routing\RouteBuilder->rebuild() (Line: 205)
Drupal\Core\Routing\RouteBuilder->rebuildIfNeeded() (Line: 91)
Drupal\Core\ProxyClass\Routing\RouteBuilder->rebuildIfNeeded() (Line: 38)
PanKM_install()
call_user_func_array('PanKM_install', Array) (Line: 391)
Drupal\Core\Extension\ModuleHandler->invoke('PanKM', 'install') (Line: 287)
Drupal\Core\Extension\ModuleInstaller->install(Array, ) (Line: 83)
Drupal\Core\ProxyClass\Extension\ModuleInstaller->install(Array, ) (Line: 1571)
install_install_profile(Array) (Line: 661)
install_run_task(Array, Array) (Line: 539)
install_run_tasks(Array) (Line: 116)
install_drupal(Object) (Line: 44)

Any solution to this?

My "Checklist API" module version is 8.x-1.7.

TravisCarden’s picture

@Aswathy Ajish, your problem is actually in SEO Checklist. Please see #2901338: RuntimeException "Recursive router rebuild detected.": race conditions.

AswathyAjish’s picture

Earlier I was using the SEO checklist module with version 8.x-4.0. Now I switched to the latest release 8.x-4.1 and my problem is solved.

My checklist API module's version is 8.x-1.7.