Page MenuHomePhabricator

eswiki: Mentee Graduation is not taking temporary users into account
Closed, ResolvedPublicPRODUCTION ERROR

Description

Error
  • mwversion: 1.46.0-wmf.5
  • timestamp: 2025-12-13T13:31:48.974Z
  • phpversion: 8.3.26
  • reqId: e31f6968-54f9-4bf7-9c73-9fb3ddea5047
  • Find reqId in Logstash
normalized_message
[{reqId}] {exception_url}   InvalidArgumentException: MediaWiki\User\Options\UserOptionsManager::saveOptionsInternal was called on IP or temporary user
FrameLocationCall
from/srv/mediawiki/php-1.46.0-wmf.5/includes/User/Options/UserOptionsManager.php(365)
#0/srv/mediawiki/php-1.46.0-wmf.5/includes/User/Options/UserOptionsManager.php(340)MediaWiki\User\Options\UserOptionsManager->saveOptionsInternal(MediaWiki\User\User)
#1/srv/mediawiki/php-1.46.0-wmf.5/extensions/GrowthExperiments/includes/Mentorship/MentorManager.php(302)MediaWiki\User\Options\UserOptionsManager->saveOptions(MediaWiki\User\User)
#2/srv/mediawiki/php-1.46.0-wmf.5/extensions/GrowthExperiments/includes/Mentorship/MenteeGraduation.php(63)GrowthExperiments\Mentorship\MentorManager->setMentorshipStateForUser(MediaWiki\User\User, int)
#3/srv/mediawiki/php-1.46.0-wmf.5/extensions/GrowthExperiments/includes/Mentorship/MediaWikiEventIngress/PageRevisionUpdatedIngress.php(38)GrowthExperiments\Mentorship\MenteeGraduation->graduateUserFromMentorship(MediaWiki\User\User)
#4/srv/mediawiki/php-1.46.0-wmf.5/extensions/GrowthExperiments/includes/Mentorship/MediaWikiEventIngress/PageRevisionUpdatedIngress.php(24)GrowthExperiments\Mentorship\MediaWikiEventIngress\PageRevisionUpdatedIngress->handleMenteeGraduation(MediaWiki\User\User)
#5/srv/mediawiki/php-1.46.0-wmf.5/includes/DomainEvent/EventDispatchEngine.php(205)GrowthExperiments\Mentorship\MediaWikiEventIngress\PageRevisionUpdatedIngress->handlePageRevisionUpdatedEvent(MediaWiki\Page\Event\PageLatestRevisionChangedEvent)
#6/srv/mediawiki/php-1.46.0-wmf.5/includes/DomainEvent/EventDispatchEngine.php(194)MediaWiki\DomainEvent\EventDispatchEngine->invoke(array, MediaWiki\Page\Event\PageLatestRevisionChangedEvent)
#7/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/MWCallableUpdate.php(52)MediaWiki\DomainEvent\EventDispatchEngine->MediaWiki\DomainEvent\{closure}(string)
#8/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/DeferredUpdates.php(445)MediaWiki\Deferred\MWCallableUpdate->doUpdate()
#9/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/DeferredUpdates.php(187)MediaWiki\Deferred\DeferredUpdates::attemptUpdate(MediaWiki\Deferred\MWCallableUpdate)
#10/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/DeferredUpdates.php(274)MediaWiki\Deferred\DeferredUpdates::run(MediaWiki\Deferred\MWCallableUpdate)
#11/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/DeferredUpdatesScope.php(229)MediaWiki\Deferred\DeferredUpdates::MediaWiki\Deferred\{closure}(MediaWiki\Deferred\MWCallableUpdate, int)
#12/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/DeferredUpdatesScope.php(158)MediaWiki\Deferred\DeferredUpdatesScope->processStageQueue(int, int, Closure)
#13/srv/mediawiki/php-1.46.0-wmf.5/includes/Deferred/DeferredUpdates.php(268)MediaWiki\Deferred\DeferredUpdatesScope->processUpdates(int, Closure)
#14/srv/mediawiki/php-1.46.0-wmf.5/includes/MediaWikiEntryPoint.php(656)MediaWiki\Deferred\DeferredUpdates::doUpdates()
#15/srv/mediawiki/php-1.46.0-wmf.5/includes/MediaWikiEntryPoint.php(478)MediaWiki\MediaWikiEntryPoint->restInPeace()
#16/srv/mediawiki/php-1.46.0-wmf.5/includes/MediaWikiEntryPoint.php(436)MediaWiki\MediaWikiEntryPoint->doPostOutputShutdown()
#17/srv/mediawiki/php-1.46.0-wmf.5/includes/MediaWikiEntryPoint.php(193)MediaWiki\MediaWikiEntryPoint->postOutputShutdown()
#18/srv/mediawiki/php-1.46.0-wmf.5/api.php(30)MediaWiki\MediaWikiEntryPoint->run()
#19/srv/mediawiki/w/api.php(3)require(string)
#20{main}
Impact
Notes

Details

Request URL
https://es.wikipedia.org/w/api.php
Related Changes in Gerrit:

Event Timeline

Logstash is reporting this only for eswiki. This makes sense, because mentee graduation is enabled on a small amount of wikis (those where admins found it in CC, plus eswiki which asked for this), specifically:

  • eswiki (we enabled this in T403563)
  • wawiki
  • fawiki
  • ruwiki

(found via global-search, by searching for GEMentorshipStartOptedOutThresholds)

Out of those wikis, ruwiki doesn't have Temporary accounts yet (the only such wiki), wawiki is very small (and also has very weird thresholds, 10k edits and 1461 days to be graduated) and eswiki is producing those errors. Naively, I'd expect fawiki to produce them as well, but that is not the case.

Another interesting part is that the errors are only produced on kube-mw-api-ext, never for web requests. I decided to check what kind of requests causes this.

Excerpts from Logstash:

Dec 16, 2025 @ 13:43:27.056	exception	kube-mw-api-ext	eswiki	[5becf5f5-12ec-44d9-aba8-f5c0974e7449] /w/api.php   InvalidArgumentException: MediaWiki\User\Options\UserOptionsManager::saveOptionsInternal was called on IP or temporary user
Dec 14, 2025 @ 19:01:09.365	exception	kube-mw-api-ext	eswiki	[cc1dd33c-79e0-429b-8e9d-be0fdbc1c007] /w/api.php   InvalidArgumentException: MediaWiki\User\Options\UserOptionsManager::saveOptionsInternal was called on IP or temporary user
Dec 14, 2025 @ 14:22:41.598	exception	kube-mw-api-ext	eswiki	[fb8cd242-15b0-4c20-9fd8-0b40a1562ff9] /w/api.php   InvalidArgumentException: MediaWiki\User\Options\UserOptionsManager::saveOptionsInternal was called on IP or temporary user

Matching records from event.mediawiki_api_requests (WMF-NDA only):

{P86677}

All those requests were made by Mobileapps/WMF user agent, which is the mobileapps service. The exact API calls vary, there is action=parse and action=query (for various page properties). Why would _those_ calls generate a deferred update like this?

All those requests were made by Mobileapps/WMF user agent, which is the mobileapps service. The exact API calls vary, there is action=parse and action=query (for various page properties). Why would _those_ calls generate a deferred update like this?

And even if they do... Those requests are not authenticated (see performer in the paste above). How would MenteeGraduation::shouldUserBeGraduated ever be true for an anonymous user? In a debug shell.php session, that seems to be false (as expected):

[urbanecm@deploy2002 ~]$ mw-debug-repl eswiki
Becoming root...
Finding a mw-debug pod in codfw...
Now running shell.php for eswiki inside pod/mw-debug.codfw.pinkunicorn-7b6dbd7cd4-642wb on release pinkunicorn...
Psy Shell v0.12.10 (PHP 8.3.26 — cli) by Justin Hileman
> \MediaWiki\MediaWikiServices::getInstance()->get('GrowthExperimentsMenteeGraduation')
= GrowthExperiments\Mentorship\MenteeGraduation {#5359}

> \MediaWiki\MediaWikiServices::getInstance()->get('GrowthExperimentsMenteeGraduation')->shouldUserBeGraduated(new \MediaWiki\User\User)
= false

>

Fixing this is quite straightforward (we just add "is named account" to the conditions in MenteeGraduation::shouldUserBeGraduated), but I'd like to first understand how/why is this happening...

Also, why is this not happening outside of API requests? Or, based on the 3 random requests I checked above, outside of Mobileapps API requests?

Urbanecm_WMF triaged this task as High priority.

Change #1220384 had a related patch set uploaded (by Urbanecm; author: Urbanecm):

[mediawiki/extensions/GrowthExperiments@master] fix(Mentorship): Do not run MenteeGraduation for temporary accounts

https://gerrit.wikimedia.org/r/1220384

Thanks @Michael for prompting me to realise what the case here is.

Change #1220384 merged by jenkins-bot:

[mediawiki/extensions/GrowthExperiments@master] fix(Mentorship): Do not run MenteeGraduation for temporary accounts

https://gerrit.wikimedia.org/r/1220384

Etonkovidova subscribed.

https://logstash.wikimedia.org/goto/c1eb855a9234fb72b448608d1e97c76f - last timestamp Jan 8, 2026 @ 19:22:03.380. No errors reported for mwversion: 1.46.0-wmf.10.