Page MenuHomePhabricator

PHP warnings from ParserOptions::optionsHash
Closed, DuplicatePublic

Description

Example trace:

[30-Sep-2020 14:36:01 UTC] PHP Warning:  Invalid argument supplied for foreach() in /srv/mediawiki/tags/2020-09-25_13:55:54/includes/parser/ParserOptions.php on line 1411
[2020-09-30 14:36:01] error.ERROR: [6380379351ad2a807748480b] /wiki/Support   ErrorException from line 1397 of /srv/mediawiki/tags/2020-09-25_13:55:54/includes/parser/ParserOptions.php: PHP Warning: array_intersec
t(): Expected parameter 1 to be an array, null given {"exception":"[object] (ErrorException(code: 0): PHP Warning: array_intersect(): Expected parameter 1 to be an array, null given at /srv/mediawiki/tags/2020-09-
25_13:55:54/includes/parser/ParserOptions.php:1397)
[stacktrace]
#0 [internal function]: MWExceptionHandler::handleError(2, 'array_intersect...', '/srv/mediawiki/...', 1397, Array)
#1 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/parser/ParserOptions.php(1397): array_intersect(NULL, Array, Array)
#2 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/parser/ParserCache.php(251): ParserOptions->optionsHash(NULL, Object(Title))
#3 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/parser/ParserCache.php(283): ParserCache->getKey(Object(WikiPage), Object(ParserOptions), 0)
#4 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/page/WikiPage.php(1208): ParserCache->get(Object(WikiPage), Object(ParserOptions))
#5 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/page/Article.php(2307): WikiPage->getParserOutput(Object(ParserOptions), NULL)
#6 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/classes/View.php(1413): Article->getParserOutput(NULL)
#7 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/classes/View.php(1570): LqtView->showPostBody(Object(Article), NULL)
#8 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/classes/View.php(1826): LqtView->showThreadBody(Object(Thread))
#9 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/classes/View.php(2169): LqtView->showSingleThread(Object(Thread))
#10 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/pages/TalkpageView.php(362): LqtView->showThread(Object(Thread))
#11 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/classes/Dispatch.php(66): TalkpageView->show()
#12 /srv/mediawiki/tags/2020-09-25_13:55:54/extensions/LiquidThreads/classes/Dispatch.php(222): LqtDispatch::talkpageMain(Object(OutputPage), Object(Article), Object(Title), Object(User), Object(WebRequest))
#13 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/HookContainer/HookContainer.php(331): LqtDispatch::tryPage(Object(OutputPage), Object(Article), Object(Title), Object(User), Object(WebRequest), Object(MediaWik
i))
#14 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/HookContainer/HookContainer.php(138): MediaWiki\\HookContainer\\HookContainer->callLegacyHook('MediaWikiPerfor...', Array, Array, Array)
#15 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/HookContainer/HookRunner.php(2543): MediaWiki\\HookContainer\\HookContainer->run('MediaWikiPerfor...', Array)
#16 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/MediaWiki.php(499): MediaWiki\\HookContainer\\HookRunner->onMediaWikiPerformAction(Object(OutputPage), Object(Article), Object(Title), Object(User), Object(WebR
equest), Object(MediaWiki))
#17 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/MediaWiki.php(313): MediaWiki->performAction(Object(Article), Object(Title))
#18 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/MediaWiki.php(940): MediaWiki->performRequest()
#19 /srv/mediawiki/tags/2020-09-25_13:55:54/includes/MediaWiki.php(543): MediaWiki->main()
#20 /srv/mediawiki/tags/2020-09-25_13:55:54/index.php(53): MediaWiki->run()
#21 /srv/mediawiki/tags/2020-09-25_13:55:54/index.php(46): wfIndexMain()
#22 {main}
","exception_id":"6380379351ad2a807748480b","exception_url":"/wiki/Support","caught_by":"mwe_handler"} []

Must have been introduced in last 7 days.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald TranscriptSep 30 2020, 2:42 PM

There seems to be an backwards incompatible change in parser cache / parser options because the error happens on the deployed version, not on the canary testing version (but seems to have started happening after I visited that page on canary).

@Pchelolo Any idea what might be happening here?

For convenience, the area of code in ParserOptions is:

1391         public function optionsHash( $forOptions, $title = null ) {
1392                 global $wgRenderHashAppend;
1393 
1394                 $inCacheKey = self::allCacheVaryingOptions();
1395 
1396                 // Resolve any lazy options
1397                 $lazyOpts = array_intersect( $forOptions, $inCacheKey, array_keys( self::$lazyOptions ) );
1398                 foreach ( $lazyOpts as $k ) {
1399                         $this->lazyLoadOption( $k );
1400                 }
1401 
1402                 $options = $this->options;
1403                 $defaults = self::getCanonicalOverrides() + self::getDefaults();
1404 
1405                 // We only include used options with non-canonical values in the key
1406                 // so adding a new option doesn't invalidate the entire parser cache.
1407                 // The drawback to this is that changing the default value of an option
1408                 // requires manual invalidation of existing cache entries, as mentioned
1409                 // in the docs on the relevant methods and hooks.
1410                 $values = [];
1411                 foreach ( array_intersect( $inCacheKey, $forOptions ) as $option ) {

This error has origin from https://gerrit.wikimedia.org/r/c/mediawiki/core/+/629403. and other caching side effects, as I noticed it first after pulling that patch at the time. The patch was a revert, but it has since been restored again (with modification).

The code with the initial patch revert had this in ParserCache::getKey (nullable property access):

// $optionsKey->mUsedOptions is set by save() by calling ParserOutput::getUsedOptions()
$usedOptions = $optionsKey->mUsedOptions;

It was later reverted again (restored) in r629405 and modified to call CacheTime::getUsedOptions() which does not return null.

// $optionsKey->mUsedOptions is set by save() by calling ParserOutput::getUsedOptions()
$usedOptions = $optionsKey->getUsedOptions();

Before all these, the code was indeed using the property, but the series of changes and you know cache....