Page MenuHomePhabricator

Singleton was called with no singleton theme set
Open, Needs TriagePublicBUG REPORT

Description

Hello, since I upgraded from MediaWiki 1.40.0 to 1.41.0, my Nginx log file is flooded with this error:

2024/03/15 02:58:42 [error] 12345#0: *1234567 FastCGI sent in stderr: "PHP message: PHP Fatal error:  OOUI\Exception: OOUI\Theme::singleton was called with no singleton theme set. in /path/to/my/wiki/vendor/oojs/oojs-ui/php/Theme.php:31
Stack trace:
#0 /path/to/my/wiki/vendor/oojs/oojs-ui/php/Element.php(259): OOUI\Theme::singleton()
#1 /path/to/my/wiki/vendor/oojs/oojs-ui/php/Tag.php(507): OOUI\Element->toString()
#2 /path/to/my/wiki/extensions/VisualEditor/includes/Hooks.php(244): OOUI\Tag->__toString()
#3 /path/to/my/wiki/includes/HookContainer/HookContainer.php(161): MediaWiki\Extension\VisualEditor\Hooks->onTextSlotDiffRendererTablePrefix()
#4 /path/to/my/wiki/includes/HookContainer/HookRunner.php(1334): MediaWiki\HookContainer\HookContainer->run()
#5 /path/to/my/wiki/includes/diff/TextSlotDiffRenderer.php(273): MediaWiki\HookContainer\HookRunner->onTextSlotDiffRendererTablePrefix()
#6 /path/to/my/wiki/includes/diff/DifferenceEngine.php(942): TextSlotDiffRenderer->getTablePrefix()
#7 /path/to/my/wiki/includes/diff/DifferenceEngine.php(928): DifferenceEngine->showTablePrefixes()
#8 /path/to/my/wiki/includes/page/Article.php(979): DifferenceEngine->showDiffPage()
#9 /path/to/my/wiki/includes/page/Article.php(490): Article->showDiffPage()
#10 /path/to/my/wiki/includes/actions/ViewAction.php(78): Article->view()
#11 /path/to/my/wiki/includes/MediaWiki.php(583): ViewAction->show()
#12 /path/to/my/wiki/includes/MediaWiki.php(363): MediaWiki->performAction()
#13 /path/to/my/wiki/includes/MediaWiki.php(960): MediaWiki->performRequest()
#14 /path/to/my/wiki/includes/MediaWiki.php(613): MediaWiki->main()
#15 /path/to/my/wiki/index.php(50): MediaWiki->run()
#16 /path/to/my/wiki/index.php(46): wfIndexMain()
#17 {main}" while reading response header from upstream, client: 123.45.67.89, server: my.wiki.com, request: "GET /w/index.php?diff=193481&oldid=prev&title=Article_Name HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: " my.wiki.com"

When I disable the VisualEditor extension, the error is gone.

Steps to replicate the issue:

  • Go to the latest revision of an article (NSFW).
  • Add "&diff=prev" to that URL (NSFW).

What happens?

The browser shows a blank page or HTTP error 500 and the error mentioned above is added to the log file.

What should have happened instead?

A page like this should be shown with the text: "(No difference)".

Software version:

OpenBSD 7.4, Nginx 1.24.0, PHP 8.1.25 (fpm-fcgi), MariaDB 10.9.6, Memcached 1.6.15, and MediaWiki 1.41.0, with REL1_41 extensions.

Event Timeline

We found similar messages in our logs, but &diff=prev works for us and seems to not be the reason for the problem.
(Example link similar to OP's one works fine: Click here (SFW))

We're not sure where it comes from.

[Tue Mar 26 14:53:53.221941 2024] [proxy_fcgi:error] [pid 3591409] [client 172.70.42.174:0] AH01071: Got error 'PHP message: PHP Fatal error: OOUI\\Exception: OOUI\\Theme::singleton was called with no singleton theme set. in /var/www/vhosts/domain.com/httpdocs/vendor/oojs/oojs-ui/php/Theme.php:31
Stack trace:
#0 /var/www/vhosts/domain.com/httpdocs/vendor/oojs/oojs-ui/php/Element.php(259): OOUI\\Theme::singleton()
#1 /var/www/vhosts/domain.com/httpdocs/vendor/oojs/oojs-ui/php/Tag.php(507): OOUI\\Element->toString()\
#2 /var/www/vhosts/domain.com/httpdocs/extensions/VisualEditor/includes/Hooks.php(244): OOUI\\Tag->__toString()\
#3 /var/www/vhosts/domain.com/httpdocs/includes/HookContainer/HookContainer.php(161): MediaWiki\\Extension\\VisualEditor\\Hooks->onTextSlotDiffRendererTablePrefix()\
#4 /var/www/vhosts/domain.com/httpdocs/includes/HookContainer/HookRunner.php(1332): MediaWiki\\HookContainer\\HookContainer->run()
#5 /var/www/vhosts/domain.com/httpdocs/includes/diff/TextSlotDiffRenderer.php(273): MediaWiki\\HookContainer\\HookRunner->onTextSlotDiffRendererTablePrefix()\n#6 /var/www/vhosts/domain.com/htt...'

Ubuntu 22.04 LTS, PHP 8.3.4, MediaWiki 1.41.0

I just upgraded to MediaWiki version 1.41.1 but it didn't fix the error.

I also observe this exception on MW 1.41.1 with VE REL1_41 on PHP 7.4. I wonder how crawlers find these links, they are not displayed by MediaWiki in the history page, so either they appear somewhere I’m not aware, either they are constructed by MediaWiki-optimised crawlers to crawl the histories.

We found similar messages in our logs, but &diff=prev works for us and seems to not be the reason for the problem.
(Example link similar to OP's one works fine: Click here (SFW))

You have also the issue: normal diffs works fine, but it’s the diff between the first revision in the history and the previous one (which don’t exist, but it should display a nice error); on your example it is this link.

I completed the stacktrace in the description (log_errors_max_len has to be set to a larger value than 1024, like 2048).

Below is a normal stacktrace when viewing a diff:

#0  MediaWiki\Output\OutputPage::setupOOUI() called at [/path/to/my/wiki/includes/Output/OutputPage.php:4717]
#1  MediaWiki\Output\OutputPage->enableOOUI() called at [/path/to/my/wiki/extensions/VisualEditor/includes/Hooks.php:202]
#2  MediaWiki\Extension\VisualEditor\Hooks->onDifferenceEngineViewHeader() called at [/path/to/my/wiki/includes/HookContainer/HookContainer.php:161]
#3  MediaWiki\HookContainer\HookContainer->run() called at [/path/to/my/wiki/includes/HookContainer/HookRunner.php:1442]
#4  MediaWiki\HookContainer\HookRunner->onDifferenceEngineViewHeader() called at [/path/to/my/wiki/includes/diff/DifferenceEngine.php:724]
#5  DifferenceEngine->showDiffPage() called at [/path/to/my/wiki/includes/page/Article.php:979]
#6  Article->showDiffPage() called at [/path/to/my/wiki/includes/page/Article.php:490]
#7  Article->view() called at [/path/to/my/wiki/includes/actions/ViewAction.php:78]
#8  ViewAction->show() called at [/path/to/my/wiki/includes/MediaWiki.php:583]
#9  MediaWiki->performAction() called at [/path/to/my/wiki/includes/MediaWiki.php:363]
#10 MediaWiki->performRequest() called at [/path/to/my/wiki/includes/MediaWiki.php:960]
#11 MediaWiki->main() called at [/path/to/my/wiki/includes/MediaWiki.php:613]
#12 MediaWiki->run() called at [/path/to/my/wiki/index.php:50]
#13 wfIndexMain() called at [/path/to/my/wiki/index.php:46]

The difference is in DifferenceEngine.php: when there is an old revision, the hook DifferenceEngineViewHeader is called by VisualEditor, which enables OOUI ($output->enableOOUI()), else it is not called and OOUI triggers an exception.


Fix: It can be fixed in the VisualEditor by copying the code from MediaWiki\Extension\VisualEditor\Hooks::onDifferenceEngineViewHeader (file extensions/VisualEditor/includes/Hooks.php) into MediaWiki\Extension\VisualEditor::onTextSlotDiffRendererTablePrefix before the use of ButtonWidget:

@@ -227,6 +227,16 @@ class Hooks implements
 			return;
 		}
 
+		$output->addModuleStyles( [
+			'ext.visualEditor.diffPage.init.styles',
+			'oojs-ui.styles.icons-accessibility',
+			'oojs-ui.styles.icons-editing-advanced'
+		] );
+		// T344596: Must load this module unconditionally. The TextSlotDiffRendererTablePrefix hook
+		// below doesn't run when the diff is e.g. a log entry with no change to the content.
+		$output->addModules( 'ext.visualEditor.diffPage.init' );
+		$output->enableOOUI();
+
 		$parts['50_ve-init-mw-diffPage-diffMode'] = '<div class="ve-init-mw-diffPage-diffMode">' .
 			// Will be replaced by a ButtonSelectWidget in JS
 			new ButtonGroupWidget( [

But probably the call to the hook DifferenceEngineViewHeader is not needed in this case.

An alternative easy fix is to in includes/diff/DifferenceEngine.php:

@@ -923,5 +923,3 @@ class DifferenceEngine extends ContextSource {
 			// Check if inline switcher will be needed
-			if ( $this->getTextDiffer()->hasFormat( 'inline' ) ) {
-				$out->enableOOUI();
-			}
+			$out->enableOOUI();

Fix: It can be fixed in the VisualEditor by copying the code from MediaWiki\Extension\VisualEditor\Hooks::onDifferenceEngineViewHeader (file extensions/VisualEditor/includes/Hooks.php) into MediaWiki\Extension\VisualEditor::onTextSlotDiffRendererTablePrefix before the use of ButtonWidget:

It works perfectly now! Thank you so much for your help! Cheers and all the best!

Ah, you were right! Also applied that fix and the problem is resolved for now.