Problem/Motivation

Some install requirement errors in MongoDB and MongoDB Watchdog crash the install with a TypeError, or show a garbled message, instead of reporting the error.

On install, drupal_check_module() displays the description of each error. When the error also has a value, core treats it as a version number, and shows @description (Currently using @title version @value). Html::escape() is typed string $text since Drupal 11.0.0, and was untyped in 10.x, so the result depends on what the description holds:

  • RequirementsChecker::checkDatabaseAliasConsistency(), missing logger alias: message in value, no description. On 11.x and 12.x, TypeError: Drupal\Component\Utility\Html::escape(): Argument #1 ($text) must be of type string, null given. On 10.x, it shows " (Currently using MongoDB watchdog version Missing `logger` database alias in settings.)".
  • RequirementsChecker::checkDatabaseAliasConsistency(), logger alias on the same database as another alias: it shows "Those databases would also be dropped when uninstalling the watchdog module. (Currently using MongoDB watchdog version The `logger` alias points to the same database as `default`.)", on all versions.
  • MongodbRequirements::check(), a database referencing an undefined client: the description is an item_list render array. On 11.x and 12.x, TypeError: Drupal\Component\Utility\Html::escape(): Argument #1 ($text) must be of type string, array given. On 10.x, TypeError: htmlspecialchars(): Argument #1 ($string) must be of type string, array given.
  • MongodbRequirements::checkExtension(), extension not loaded: message in description and "Extension not loaded" in value, so it shows "… (Currently using MongoDB version Extension not loaded)".
  • MongodbRequirements::checkExtensionVersion(), extension older than 1.1.7: neither value nor description, so an empty message.

#3626729: Drupal 12 pre-release compatibility made the missing alias case report a requirement error instead of throwing, which exposed the first case.

Steps to reproduce

  1. Use 8.x-2.x at or after 48fdf33, on Drupal 10.6, 11.4 or 12.0.0-beta1.
  2. Leave $settings['mongodb'] without a logger alias, for example with settings.local.php not included.
  3. Run drush en mongodb_watchdog.

Expected: the error "Missing `logger` database alias in settings."
Actual: the TypeError above on 11.x and 12.x, or the garbled message on 10.x, after "Undefined array key "description"" warnings from install.inc.

For the other cases, point the logger alias at the same database as default, or point a database at a client missing from clients, and enable the corresponding module.

Proposed resolution

Every error that can be reported on install carries its message as a string description, and no value:

  • Missing logger alias: move the message from value to description.
  • Duplicate logger database, and extension not loaded: merge the value into the description.
  • Database on an undefined client: report the warnings as a string description instead of an item_list.
  • Extension too old: set the version message as the description.

Add kernel tests that run drupal_check_module() for each case that settings can reproduce, and check the error message.

Remaining tasks

  • Fix
  • Test
  • Review

User interface changes

Install errors show their message instead of crashing or showing it as a version number.

API changes

None.

Data model changes

None.

AI disclosure

AI Disclosure: I used Claude Code to identify, triage and prepare this bug report.

CommentFileSizeAuthor
#6 review-3627745-details-26J07.txt3.08 KBfgm

Issue fork mongodb-3627745

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

matthand created an issue. See original summary.

matthand’s picture

Issue summary: View changes
matthand’s picture

Assigned: Unassigned » matthand
Status: Active » Needs work

I'm picking this up, should have an MR soon.

matthand’s picture

Status: Needs work » Needs review

The MR 57 adds the missing description to both requirement errors:

  • RequirementsChecker::checkDatabaseAliasConsistency(): the missing alias message moves from value to description, rather than adding a second message as proposed in the summary. On install, core shows value as "(Currently using MongoDB watchdog version …)", and hook_requirements() reserves it for version numbers in that phase. The string is unchanged, so translations still apply.
  • MongodbRequirements::checkExtensionVersion(): when the check fails, the version message is now also the description, so the error is no longer empty.

RequirementsCheckerTest is a new kernel test that needs no MongoDB server. It calls drupal_check_module() without a logger alias and expects the error message. On 12.0.0-beta1 it fails with the TypeError from the summary without the fix, and passes with it. The rest of the module's tests also pass on 12.0.0-beta1. The extension version error has no test, because the extension version cannot be faked in a test.

On 10.x and 11.x, the same case did not throw. It showed an error with an empty message, along with deprecation notices, and the fix makes it readable there too. The CI jobs for the previous major and minor versions will run the new test.

fgm’s picture

Status: Needs review » Needs work
StatusFileSize
new3.08 KB

Thanks @matthand: moving the message to description is the right fix, better than the summary's proposal, and the new test passes on 10.6, 11.4 and 12.0.0-beta1.

Two things change the scope, so I have updated the issue summary:

  • This is not Drupal 12 only. Html::escape() has been typed string since 11.0.0, so the missing alias case throws on every 11.x too. On 10.x it does not throw, but the message is not empty either: core shows it as a version number, " (Currently using MongoDB watchdog version Missing `logger` database alias in settings.)". The MR description should say so.
  • Three more requirement errors break on install in the same way, in the two classes this MR already touches. A database referencing an undefined client throws a TypeError on 10.x, 11.x and 12.x, because its description is a render array. The duplicate logger database and the missing extension both keep a value, so core shows their message as a version number.

They share one cause: on install, core displays description and treats value as a version. Fixing them here keeps the rule in one place: every error reachable on install has a string description and no value.

Could you extend the MR to cover them, with tests for the cases settings can reproduce? The attached file has the reproduction settings and the exact messages on each version, for you or your agent.

I have also retitled the issue to match.

fgm’s picture

Issue summary: View changes
fgm’s picture

Title: Installing MongoDB Watchdog without a logger database alias throws a TypeError on Drupal 12 » Fix multiple install requirement errors
matthand’s picture

Status: Needs work » Needs review

Thanks @fgm. I extended MR !57 as you suggested in #6. Every requirement error that can come up on install now has a string description and no value, and both requirement classes state that rule in their docblock.

  • Database referencing an undefined client: MongodbRequirements::checkDatabases() now sets its own error, like the other check*() methods. The "Database … references undefined client …" messages are joined into a string description, instead of an item list render array. The item list is kept for a valid configuration.
  • Duplicate logger database: RequirementsChecker::checkDatabaseAliasConsistency() puts both sentences in the description.
  • Extension not loaded: MongodbRequirements::checkExtension() drops the "Extension not loaded" value.

No translatable string changes. On the status report, these errors now show only their description, without the short value.

Tests:

  • RequirementsCheckerTest::testDuplicateLoggerDatabase(), next to the existing missing alias test.
  • New MongodbRequirementsTest::testUndefinedClient(), with two undefined clients, so it also checks that the messages are joined.

On 11.4, without the fix, they fail with the TypeError and the "(Currently using … version …)" message from your details file. With it, the full module suite passes, and phpstan and phpcs are clean. The new tests also pass on 12.x. The extension cases still have no test, because they need PHP without the extension, or an older version of it.

One note on your case 2 settings: 'clients' => ['default' => []] also reports default as undefined, because the check treats an empty client configuration as missing. This behavior predates this MR, so I left it as is. The test uses a client with a URI instead.

I have also updated the MR title and description: the missing alias case throws on all of 11.x, not only 12.x.

The only failure on the MR pipeline is phpunit (next major), which is allowed to fail, and it is unrelated to this MR:

Drupal\Tests\mongodb_storage\Kernel\SqlImportTest::testImportActual with data set #0
Failed asserting that 4 matches expected 0.

Core commit 5c8d732 (#3613347 "Re-use container in kernel tests", committed 2026-10-10) removed the in-memory key-value override from KernelTestBase, so kernel tests now write key-value data to the SQL database. HookCollectorKeyValueWritePass writes 4 hook_data rows to key_value while the test container is built, so the table is no longer empty when SqlImportTest starts. The 12.x job passed before that commit, and simulating the change locally gives the same failure. I will file a follow-up issue for it, to keep this MR focused on the requirement checks.

matthand’s picture

New D12 test fail issue after latest core changes merged is filed here: #3629965: SqlImportTest fails on next major: key_value table no longer empty in kernel tests

fgm’s picture

Status: Needs review » Needs work

Thanks for filing #3629965: SqlImportTest fails on next major: key_value table no longer empty in kernel tests. It won't block the 2.2 release since it's on D12 only (although it's nice if we can fix it), but it will have to be fixed by 2.3.

I think the pre-existing check, which is too strict and rejects the valid empty config, needs to match the actual needs of the ClientFactory: with !array_key_exists($client, $aliases) or !isset($aliases[$client]) instead of empty(), since you're fixing that area, and with that case added to MongodbRequirementsTest.

Maybe, here or in a follow-up, ClientFactoryTest::testGetHappy() and testGetSadBadAlias() could also become a tabular test with a data provider, covering the empty config and a few variants: that's useful to show users the expected shapes and the shapes that don't work. The cases that rely on the default URI should check the client's URI without connecting, since CI's server is not on localhost.

Also, the RequirementsChecker docblock says errors have no value, but checkRequestTracking() keeps "No mod_unique_id" as its value. Install never reaches it, though, since it reads the default configuration, where request_tracking is false. Scoping the sentence to errors reachable on install would keep it accurate.

Finally, I would prefer to keep "Inconsistent database/client settings." as the start of the description: dropping the value fixes install, but on the status report and update.php the error then has no summary at all. As a prefix, it shows in every phase. WDYT?

Tested locally on D10, 11, 12 with MongoDB 7.0, 8.0, and 8.3