Page MenuHomePhabricator

Installer sets a $wgSQLiteDataDir to a relative path, causing DB access exceptions when running maintenance scripts from any directory other than MediaWiki root ($IP)
Open, Needs TriagePublic

Description

This may obsolete T359823 and T306184 depends on the root cause, but I've found a common element here that I think is worth capturing in a separate task.

mediawiki/extensions/Flow$ php maintenance/convertToText.php --page 'Talk:Snippets/Auto-number headings' --remoteapi 'https://www.mediawiki.org/w/api.php'

LogicException from line 475 of /Users/krinkle/Development/mediawiki/includes/language/MessageCache.php: Process cache for 'en' should be set by now.
#0 /Users/krinkle/Development/mediawiki/includes/language/MessageCache.php(350): MessageCache->loadUnguarded('en', NULL)
…
#5 /Users/krinkle/Development/mediawiki/includes/Message/Message.php(1554): MessageCache->get('signature', true, Object(LanguageEn), 'signature')
#6 /Users/krinkle/Development/mediawiki/includes/Message/Message.php(1035): MediaWiki\Message\Message->fetchMessage()
#7 /Users/krinkle/Development/mediawiki/includes/Message/Message.php(1125): MediaWiki\Message\Message->format('text')
#8 /Users/krinkle/Development/mediawiki/includes/parser/Parser.php(4803): MediaWiki\Message\Message->text()
#9 /Users/krinkle/Development/mediawiki/extensions/Flow/maintenance/convertToText.php(239): MediaWiki\Parser\Parser->getUserSig(Object(MediaWiki\User\User), string, false)

What I tried:

  • Load the Main_Page in a browser first, in case that's somehow able to better initialize localisation caches. (No difference)
  • Comment out various lines in LocalSettings.php relating to caching, as well as disabling other extensions. (No difference)
  • Run one of MediaWIki core's maintenance scripts. Worked fine.
  • Finally, run the exact same extension script, but from the MediaWiki core directory.... Worked fine!
mediawiki$ php extensions/Flow/maintenance/convertToText.php --page 'Talk:Snippets/Auto-number headings' --remoteapi 'https://www.mediawiki.org/w/api.php'
…

Event Timeline

I traced this down by enabling a verbose mode on the command-line, by copying the way the -d parameter works in eval.php, and adding it to the maintenance script I was working on:

class ConvertToText extends Maintenance {
	public function __construct() {
		parent::__construct();
		// \MediaWiki\Logger\LoggerFactory::registerProvider( new \MediaWiki\Logger\ConsoleSpi );
		// \MediaWiki\MediaWikiServices::resetGlobalInstance();

I then compared the output prior from the failure (ext directory) side-by-side with the debug output from the succesful run (core directory)

Fine (core directory)
php extensions/Flow/maintenance/convertToText.php --page 'Talk:Snippets/Auto-number headings' --remoteapi 'https://www.mediawiki.org/w/api.php'
[debug] Start command line script extensions/Flow/maintenance/convertToText.php
[debug] [session] SessionManager using store SqlBagOStuff
[debug] [localisation] LocalisationCache using store LCStoreStaticArray
[debug] [objectcache] MainWANObjectCache using store Wikimedia\ObjectCache\EmptyBagOStuff
[debug] [http] GET: https://www.mediawiki.org/w/api.php?vhformat=wikitext&action=flow&… HTTP/1.1 - 200 NULL
[debug] ParserFactory: using default preprocessor
[debug] [SQLBagOStuff] MainObjectStash using store SqlBagOStuff
[debug] [MessageCache] MessageCache using store SqlBagOStuff
[debug] [SQLBagOStuff] SqlBagOStuff debug: SqlBagOStuff::fetchBlobs: retrieved my_wiki:messages:en; expiry time is 99991231235959
Failing (ext dir)
php maintenance/convertToText.php --page 'Talk:Snippets/Auto-number headings' --remoteapi 'https://www.mediawiki.org/w/api.php'
[debug] Start command line script maintenance/convertToText.php
[debug] [session] SessionManager using store SqlBagOStuff
[debug] [localisation] LocalisationCache using store LCStoreStaticArray
[debug] [objectcache] MainWANObjectCache using store Wikimedia\ObjectCache\EmptyBagOStuff
[debug] [http] GET: https://www.mediawiki.org/w/api.php?vhformat=wikitext&action=flow&… HTTP/1.1 - 200 NULL
[debug] ParserFactory: using default preprocessor
[debug] [SQLBagOStuff] MainObjectStash using store SqlBagOStuff
[debug] [MessageCache] MessageCache using store SqlBagOStuff
[error] [SQLBagOStuff] Error connecting to unknown as user [Null]: SQLSTATE[HY000] [14] unable to open database file
#0 /Users/krinkle/Development/mediawiki/includes/libs/rdbms/database/DatabaseSqlite.php(195): Wikimedia\Rdbms\Database->newExceptionAfterConnectError(string)

Looking at the generated LocalSettings.php again, I realized the problem is with the sqlite data directory. The LocalSettings.php file, as generated by the Installer, e.g. for MediaWiki-Docker and Quickstart, sets the following by default:

LocalSettings.php
$wgSQLiteDataDir = "cache/";

This is fragile, as it relies on the PHP process having a certain current working directory. I fixed it for my install by setting it to __DIR__ . '/cache/' instead.

That could be a patch. Alternatively, we could fix the interpretation of the above to be done relative to MW_INSTALL_PATH if it isn't an absolute path. That seems more sustainable to me?

If I'm right about T359823, then the error message here will be different after the fix (assuming that something else in the maint script, after MessageCache, tries to access the database too), but there will still be some kind of exception.

That said, I'm already getting a different exception locally, when I try to reproduce this configuration:

Wikimedia\Rdbms\DBConnectionError from line 1131 of C:\mediawiki\core\includes\libs\rdbms\loadbalancer\LoadBalancer.php: Cannot access the database: No database connection (localhost)
matmarex renamed this task from "LogicException: Process cache for 'en' should be set by now" when running maintenance scripts from extension directory to Installer sets a $wgSQLiteDataDir to a relative path, causing DB access exceptions when running maintenance scripts from any directory other than MediaWiki root ($IP).Mar 18 2025, 1:21 AM