Page MenuHomePhabricator

APCU + languageconverter dynamic property creation error with PHP 8.4
Open, HighPublicBUG REPORT

Description

Steps to replicate the issue (include links if applicable):

  • MediaWiki 1.43.3, PHP 8.4.11,
$wgMainCacheType = CACHE_ACCEL;
$wgParserCacheType = 'apcu';
$wgMessageCacheType = 'apcu';
$wgSessionsInObjectCache = true;
$wgSessionCacheType = 'apcu';
$wgEnableSidebarCache = true;

What happens?:

Deprecated: Creation of dynamic property MediaWiki\Language\ReplacementArray::$data is deprecated in /srv/wiki.gslin.org/public/includes/libs/objectcache/APCUBagOStuff.php on line 70
[89b7981d01fd3cdada982ae7] /wiki/%E9%A6%96%E9%A1%B5 Error: Typed property MediaWiki\Language\ReplacementArray::$data must not be accessed before initialization

Backtrace:

from /srv/wiki.gslin.org/public/includes/libs/ReplacementArray.php(104)
#0 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(623): MediaWiki\Language\ReplacementArray->replace()
#1 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(602): MediaWiki\Language\LanguageConverter->translate()
#2 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(829): MediaWiki\Language\LanguageConverter->autoConvert()
#3 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(584): MediaWiki\Language\LanguageConverter->recursiveConvertTopLevel()
#4 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(829): MediaWiki\Language\LanguageConverter->autoConvert()
#5 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(793): MediaWiki\Language\LanguageConverter->recursiveConvertTopLevel()
#6 /srv/wiki.gslin.org/public/includes/language/LanguageConverter.php(781): MediaWiki\Language\LanguageConverter->convertTo()
#7 /srv/wiki.gslin.org/public/includes/parser/Parser.php(1719): MediaWiki\Language\LanguageConverter->convert()
#8 /srv/wiki.gslin.org/public/includes/parser/Parser.php(704): MediaWiki\Parser\Parser->internalParseHalfParsed()
#9 /srv/wiki.gslin.org/public/includes/content/WikitextContentHandler.php(384): MediaWiki\Parser\Parser->parse()
#10 /srv/wiki.gslin.org/public/includes/content/ContentHandler.php(1691): MediaWiki\Content\WikitextContentHandler->fillParserOutput()
#11 /srv/wiki.gslin.org/public/includes/content/Renderer/ContentRenderer.php(79): MediaWiki\Content\ContentHandler->getParserOutput()
#12 /srv/wiki.gslin.org/public/includes/Revision/RenderedRevision.php(263): MediaWiki\Content\Renderer\ContentRenderer->getParserOutput()
#13 /srv/wiki.gslin.org/public/includes/Revision/RenderedRevision.php(236): MediaWiki\Revision\RenderedRevision->getSlotParserOutputUncached()
#14 /srv/wiki.gslin.org/public/includes/Revision/RevisionRenderer.php(239): MediaWiki\Revision\RenderedRevision->getSlotParserOutput()
#15 /srv/wiki.gslin.org/public/includes/Revision/RevisionRenderer.php(172): MediaWiki\Revision\RevisionRenderer->combineSlotOutput()
#16 [internal function]: MediaWiki\Revision\RevisionRenderer->{closure:MediaWiki\Revision\RevisionRenderer::getRenderedRevision():170}()
#17 /srv/wiki.gslin.org/public/includes/Revision/RenderedRevision.php(199): call_user_func()
#18 /srv/wiki.gslin.org/public/includes/poolcounter/PoolWorkArticleView.php(106): MediaWiki\Revision\RenderedRevision->getRevisionParserOutput()
#19 /srv/wiki.gslin.org/public/includes/poolcounter/PoolWorkArticleViewCurrent.php(123): MediaWiki\PoolCounter\PoolWorkArticleView->renderRevision()
#20 /srv/wiki.gslin.org/public/includes/poolcounter/PoolCounterWork.php(171): MediaWiki\PoolCounter\PoolWorkArticleViewCurrent->doWork()
#21 /srv/wiki.gslin.org/public/includes/page/ParserOutputAccess.php(362): MediaWiki\PoolCounter\PoolCounterWork->execute()
#22 /srv/wiki.gslin.org/public/includes/page/Article.php(827): MediaWiki\Page\ParserOutputAccess->getParserOutput()
#23 /srv/wiki.gslin.org/public/includes/page/Article.php(547): Article->generateContentOutput()
#24 /srv/wiki.gslin.org/public/includes/actions/ViewAction.php(78): Article->view()
#25 /srv/wiki.gslin.org/public/includes/actions/ActionEntryPoint.php(733): ViewAction->show()
#26 /srv/wiki.gslin.org/public/includes/actions/ActionEntryPoint.php(510): MediaWiki\Actions\ActionEntryPoint->performAction()
#27 /srv/wiki.gslin.org/public/includes/actions/ActionEntryPoint.php(146): MediaWiki\Actions\ActionEntryPoint->performRequest()
#28 /srv/wiki.gslin.org/public/includes/MediaWikiEntryPoint.php(200): MediaWiki\Actions\ActionEntryPoint->execute()
#29 /srv/wiki.gslin.org/public/index.php(58): MediaWiki\MediaWikiEntryPoint->run()
#30 {main}

What should have happened instead?:

Software version (on Special:Version page; skip for WMF-hosted wikis like Wikipedia):

Other information (browser name/version, screenshots, etc.):
https://www.mediawiki.org/w/index.php?title=Project%3ASupport_desk&curid=2084484&diff=7910916#$wgMainCacheType_=_CACHE_ACCEL;_(i.e._APCU)_causes_PHP_error_on_MW_1.43.3

Details

Other Assignee
cscott

Event Timeline

TheDJ renamed this task from APCU + languageconverter error with PHP 8.4 to APCU + languageconverter dynamic property creation error with PHP 8.4.Sep 29 2025, 12:20 PM

This seems to be a bug with apcu_fetch, since ReplacementArray is not doing anything "interesting" here at all, except maybe defining __sleep unnecessarily. The data property is initialized by the constructor and there should be no way to create a ReplacementArray without initializing data.

Typing data was done in 1.43 (which would match the mw.org report), so maybe changing the type breaks unserialization somehow?

In any case, not really actionable? I don't think we promise that you can do a major version upgrade without clearing caches.

Seems like a logical assessment. Maybe we should think if there is something we can check in the update process to detect and encourage ppl to reset that cache ?

We automatically clear db-based object caches as part of update.php. For things stored in APCU, though, it seems reasonable to expect that keys are versioned or validated at runtime. An admin might manually reboot their webserver, but afaik that is not status quo and not documented or indicated as a required upgrade step.

LanguageConverter::loadTables uses the CACHE_VERSION_KEY constant in its makeKey calls. That should be bumped if the value changed in a backwards-incompatible manner.

Application logic doesn't know whether it's using SQLBagOStuff or APCU, that's a matter of confiugration.

I see update.php clears the objectcache table manually; that seems both too much (it's used as the default session store when memcache etc. is not installed) and too little. But then there isn't any obvious way to do better; APCU can be purged programmatically but just as with objectcache, it doesn't know what it's being used for so no way to tell whether it should.

Anyway, this is actually a consequence of the renamespacing, not the type hint change: eval1, eval2.

Deprecated: Creation of dynamic property MediaWiki\Language\ReplacementArray::$data is deprecated in /in/AlIPR on line 19
object(MediaWiki\Language\ReplacementArray)#1 (2) {
  ["data":"MediaWiki\Language\ReplacementArray":private]=>
  NULL
  ["data":"ReplacementArray":private]=>
  array(1) {
    [0]=>
    int(1)
  }
}

Apparently this is a known bug: https://github.com/php/php-src/issues/18542

MSantos triaged this task as High priority.Jan 12 2026, 4:07 PM