Page MenuHomePhabricator

PHP Deprecated: Use of MediaWiki\Parser\Parser::getPage without a Title set was deprecated in MediaWiki 1.34. [Called from MediaWiki\Extension\Translate\HookHandler::translateRenderParserFunction]
Open, Needs TriagePublicPRODUCTION ERROR

Description

Error
labels.normalized_message
[{reqId}] {exception_url}   PHP Deprecated: Use of MediaWiki\Parser\Parser::getPage without a Title set was deprecated in MediaWiki 1.34. [Called from MediaWiki\Extension\Translate\HookHandler::translateRenderParserFunction]
FrameLocationCall
from/srv/mediawiki/php-1.44.0-wmf.3/extensions/Translate/src/HookHandler.php(859)
#0[internal function]MWExceptionHandler::handleError(int, string, string, string, array)
#1/srv/mediawiki/php-1.44.0-wmf.3/includes/debug/MWDebug.php(386)trigger_error(string, int)
#2/srv/mediawiki/php-1.44.0-wmf.3/includes/debug/MWDebug.php(357)MediaWiki\Debug\MWDebug::sendRawDeprecated(string, bool, string)
#3/srv/mediawiki/php-1.44.0-wmf.3/includes/debug/MWDebug.php(238)MediaWiki\Debug\MWDebug::deprecatedMsg(string, string, string, int)
#4/srv/mediawiki/php-1.44.0-wmf.3/includes/GlobalFunctions.php(773)MediaWiki\Debug\MWDebug::deprecated(string, string, string, int)
#5/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(1051)wfDeprecated(string, string)
#6/srv/mediawiki/php-1.44.0-wmf.3/extensions/Translate/src/HookHandler.php(859)MediaWiki\Parser\Parser->getPage()
#7/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(3436)MediaWiki\Extension\Translate\HookHandler->translateRenderParserFunction(MediaWiki\Parser\Parser, string)
#8/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(3117)MediaWiki\Parser\Parser->callParserFunction(MediaWiki\Parser\PPTemplateFrame_Hash, string, array)
#9/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/PPFrame_Hash.php(280)MediaWiki\Parser\Parser->braceSubstitution(array, MediaWiki\Parser\PPTemplateFrame_Hash)
#10/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/PPTemplateFrame_Hash.php(100)MediaWiki\Parser\PPFrame_Hash->expand(MediaWiki\Parser\PPNode_Hash_Tree, int)
#11/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(3307)MediaWiki\Parser\PPTemplateFrame_Hash->cachedExpand(string, MediaWiki\Parser\PPNode_Hash_Tree)
#12/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/PPFrame_Hash.php(280)MediaWiki\Parser\Parser->braceSubstitution(array, MediaWiki\Parser\PPFrame_Hash)
#13/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(2951)MediaWiki\Parser\PPFrame_Hash->expand(MediaWiki\Parser\PPNode_Hash_Tree, int)
#14/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(937)MediaWiki\Parser\Parser->replaceVariables(string, MediaWiki\Parser\PPFrame_Hash)
#15/srv/mediawiki/php-1.44.0-wmf.3/includes/parser/Parser.php(4936)MediaWiki\Parser\Parser->preprocess(string, MediaWiki\Title\Title, MediaWiki\Parser\ParserOptions)
#16/srv/mediawiki/php-1.44.0-wmf.3/includes/language/MessageCache.php(1476)MediaWiki\Parser\Parser->transformMsg(string, MediaWiki\Parser\ParserOptions, null)
#17/srv/mediawiki/php-1.44.0-wmf.3/includes/language/Message/Message.php(1487)MessageCache->transform(string, bool, LanguageEn, null)
#18/srv/mediawiki/php-1.44.0-wmf.3/includes/language/Message/Message.php(1052)MediaWiki\Message\Message->transformText(string)
#19/srv/mediawiki/php-1.44.0-wmf.3/includes/language/Message/Message.php(1100)MediaWiki\Message\Message->format(string)
#20/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiUsageException.php(69)MediaWiki\Message\Message->text()
#21/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiBase.php(1667)MediaWiki\Api\ApiUsageException->__construct(MediaWiki\Api\ApiEditPage, MediaWiki\Status\Status)
#22/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiEditPage.php(556)MediaWiki\Api\ApiBase->dieStatus(MediaWiki\Status\Status)
#23/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiMain.php(1975)MediaWiki\Api\ApiEditPage->execute()
#24/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiMain.php(912)MediaWiki\Api\ApiMain->executeAction()
#25/srv/mediawiki/php-1.44.0-wmf.3/extensions/VisualEditor/includes/ApiVisualEditorEdit.php(139)MediaWiki\Api\ApiMain->execute()
#26/srv/mediawiki/php-1.44.0-wmf.3/extensions/VisualEditor/includes/ApiVisualEditorEdit.php(446)MediaWiki\Extension\VisualEditor\ApiVisualEditorEdit->saveWikitext(MediaWiki\Title\Title, string, array)
#27/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiMain.php(1975)MediaWiki\Extension\VisualEditor\ApiVisualEditorEdit->execute()
#28/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiMain.php(943)MediaWiki\Api\ApiMain->executeAction()
#29/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiMain.php(914)MediaWiki\Api\ApiMain->executeActionWithErrorHandling()
#30/srv/mediawiki/php-1.44.0-wmf.3/includes/api/ApiEntryPoint.php(153)MediaWiki\Api\ApiMain->execute()
#31/srv/mediawiki/php-1.44.0-wmf.3/includes/MediaWikiEntryPoint.php(200)MediaWiki\Api\ApiEntryPoint->execute()
#32/srv/mediawiki/php-1.44.0-wmf.3/api.php(44)MediaWiki\MediaWikiEntryPoint->run()
#33/srv/mediawiki/w/api.php(3)require(string)
#34{main}
Notes

Noted during deploy of 1.44.0-wmf.3 (T375662).

Details

Request URL
https://www.mediawiki.org/w/api.php

Event Timeline

This isn't the fault of MediaWiki-extensions-Translate. It was passed a message without a title, which should have been caught earlier. I think it's MediaWiki-Action-API's fault for not passing a title when constructing an APIUsageException, but it could also be VisualEditor's fault, because it has some weird context-passing logic.

This was supposed to be fixed by rETRA68d2e8d5ffe7: Avoid calling Parser::getPage() when no title is set but something is parsing an interface message without the interface message flag set.

Something must have changed in code outside Translate or inside wiki content. Unfortunately this doesn't look like a fun thing to debug.

This was supposed to be fixed by rETRA68d2e8d5ffe7: Avoid calling Parser::getPage() when no title is set but something is parsing an interface message without the interface message flag set.

That thing is almost in the stack trace: https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/refs/heads/wmf/1.44.0-wmf.3/includes/api/ApiUsageException.php#68 (the stack trace contains the next line) calls ->inLanguage('en'), which resets the interface message status. ->inLanguage('en')->useDatabase(false) appears nine times (plus a few times in tests) in core alone, so maybe there could be some method (e.g. ->forLogging()) that sets the language to English and disables using the database but doesn’t reset the interface message flag?

Something must have changed in code outside Translate or inside wiki content.

The stack trace goes to HookHandler::translateRenderParserFunction(), i.e. the {{#translation:}} parser function. That’s quite unusual in a message (and even more unusual in a message that isn’t supposed to use the database… but apparently transcludes a template and thus still uses it), and that could be the (on-wiki) change that triggered this warning. However, the bug is not on-wiki, as I wrote above.

Ideally we would know what that message is that is doing something weird. Unfortunately the stack trace doesn't tell us.

In order for it to reach the place in the stack trace it does, it must produce AS_HOOK_ERROR or AS_HOOK_ERROR_EXPECTED.

This means the problematic message must come from a EditFilter or EditFilterMergedContent hook.

This comment was removed by Pppery.
This comment was removed by Pppery.

Note that the template call doesn't need to be in the message - it's far more likely to be in the parameters to the message. There are a bunch of messages that include parameters with user controlled text that could trigger in this context, but the only ones that are at all plausible are AbuseFilter and Translate's syntax checker for invalid translate syntax.

I probably could produce an error in the logs by giving deliberately contrived input in both of those cases (i.e T380126 lets you parse arbitrary wikitext in this context), but I can't imagine how either could occur other than via some kind of breaching experiment. And, counter Niklas's comment earlier, I actually did find it fun reading through the code trying to imagine what could happen, although I didn't get anywhere.

Actually I could totally imaging this happening:

  • Someone tries to use VisualEditor to edit a page with on MediaWiki.org that contains pre tags, and then later a template that uses the #translation: parser function. I can't actually find such a page/template right now, but I'm sure one exists.
  • They screw up the translate syntax somehow. VisualEditor's translate integration makes this trivially easy to do.
  • T380126 means that the template gets called in the error message
  • The template uses #translation: somehow.
  • Bingo! Error!

Even if T380126 were fixed, there are no doubt plenty of other ways of causing this (i.e template calls in AbuseFilter names is another one), so what Tacsipacsi described should still be fixed. And the ApiUsageException tree should pass a title to truly render this class of errors moot once and for all.

This is rare enough it could have been broken for years until somebody happened to push the right button during the deploy.

Thanks for the fun debugging exercise! I learned quite a bit from it.

And the ApiUsageException tree should pass a title to truly render this class of errors moot once and for all.

I’m not sure if this is possible universally: not all errors belong to pages. action=edit ones are, since there’s always a page to edit, but what page to use on login or when getting the watchlist content?

Pass Special:UserLogin or Special:Watchlist respectively?

Why Special:Watchlist, why not Special:EditWatchlist or Special:EditWatchlist/raw? All three can be equally appropriate, so none of them is really appropriate.

If my hypothesis about what caused this is right then the fix for T380126 in WMF-5 will have caused this error to stop happening. Otherwise more details (i.e what the parameters of the API request are) will be needed to debug.

I don’t think this is a duplicate: T380126 is about Translate causing markup to end up in a parse with no page set (which can cause problems in any extension that hooks in the parse and relies on the page being set), while this task is about Translate not handling gracefully that markup ends up in a parse with no page set (be that parse started by any extension). If you don’t care, declining the task is okay, but it’s not a duplicate of that fixed bug.

(And there’s a third bug as well, discussed in this task: that ApiUsageException destroys the interface message flag.)