Page MenuHomePhabricator

ReplaceText jobs sometimes fail when User::getName() returns null
Open, HighPublic

Description

[2022-04-28T06:06:20.133104+00:00] exception.ERROR: [9e4f35f768c1e60ab7a28f2d] [no req]   TypeError: Return value of User::getName() must be of the type string, null returned {"exception":"[object] (TypeError(code: 0): Return value of User::getName() must be of the type string, null returned at /srv/mediawiki/tags/2022-04-27_14:01:50/includes/user/User.php:1934)
[stacktrace]
#0 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/user/User.php(3773): User->getName()
#1 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/user/User.php(1427): User->isGlobalSessionUser()
#2 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/user/User.php(1752): User->getBlockedStatus()
#3 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/Permissions/PermissionManager.php(786): User->getBlock()
#4 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/Permissions/PermissionManager.php(504): MediaWiki\\Permissions\\PermissionManager->checkUserBlock()
#5 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/Permissions/PermissionManager.php(292): MediaWiki\\Permissions\\PermissionManager->getPermissionErrorsInternal()
#6 /srv/mediawiki/tags/2022-04-27_14:01:50/extensions/ReplaceText/src/Job.php(60): MediaWiki\\Permissions\\PermissionManager->userCan()
#7 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/jobqueue/JobRunner.php(384): MediaWiki\\Extension\\ReplaceText\\Job->run()
#8 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/jobqueue/JobRunner.php(345): JobRunner->doExecuteJob()
#9 /srv/mediawiki/tags/2022-04-27_14:01:50/includes/jobqueue/JobRunner.php(249): JobRunner->executeJob()
#10 /srv/mediawiki/tags/2022-04-27_14:01:50/maintenance/runJobs.php(98): JobRunner->run()
#11 /srv/mediawiki/tags/2022-04-27_14:01:50/maintenance/doMaintenance.php(122): RunJobs->execute()
#12 /srv/mediawiki/tags/2022-04-27_14:01:50/maintenance/runJobs.php(136): require_once('/srv/mediawiki/...')
#13 {main}
","exception_url":"[no req]","reqId":"9e4f35f768c1e60ab7a28f2d","caught_by":"other"} []

Event Timeline

There hasn't been code changes to ReplaceText since February.

ReplaceTextJob does $current_user = User::newFromId( $this->params['user_id'] );.

In the logs:

2022-04-28 06:06:20 replaceText MediaWiki:Tpt-notsuitable/gsw user_id=402 target_str=<nowiki><translate></nowiki> replacement_str=$2 use_regex= edit_summary=Text replacement - "<nowiki><translate></nowiki>" to "$2" create_redirect= watch_page= doAnnounce=1 roles=["main"] namespace=8 title=Tpt-notsuitable/gsw requestId=9e4f35f768c1e60ab7a28f2d (id=54527460,timestamp=20220428060412) t=5 error=TypeError: Return value of User::getName() must be of the type string, null returned

I cannot reproduce manually:

twn:/www/translatewiki.net/logs$ php /srv/mediawiki/workdir/maintenance/shell.php 
Psy Shell v0.11.2 (PHP 7.4.28 — cli) by Justin Hileman
>>> $current_user = User::newFromId( 402 );
=> User {#3212
     +mId: 402,
     +mName: null,
     +mActorId: null,
     +mRealName: null,
     +mEmail: null,
     +mTouched: null,
     +mEmailAuthenticated: null,
     +mFrom: "id",
     +mBlockedby: -1,
     +mHideName: null,
     +mBlock: null,
   }
>>> $permissionManager = MediaWiki\MediaWikiServices::getInstance()->getPermissionManager();
=> MediaWiki\Permissions\PermissionManager {#3204}
>>> $permissionManager->userCan( 'replacetext', $current_user, Title::newFromText( 'MediaWiki:Tpt-notsuitable/gsw' ) );
=> true

It's a bit tricky to figure out why User::getName() would be trying to return null. Once reason might be that it's an anonymous user (or the user ID isn't found in the DB), and $this->mName = IPUtils::sanitizeIP( $this->getRequest()->getIP() ) returns null (which is documented to be possible). So one thing we could do is to improve error handling in case IPUtils::sanitizeIP() returns null, so we at least know what $this->getRequest()->getIP() returned.

Another possibility is that $this->mName winds up being null after load(). It's not obvious to me how it could happen, but it might. Perhaps this case could be checked and caught inside load(), to provide mroe information about what whent wrong.

abi_ triaged this task as High priority.May 10 2022, 7:02 AM

I'm able to reproduce this on Translatewiki when the jobs are run automatically via the JobQueue but not when running runJobs.php manually from the command line. I'm unable to reproduce this at all locally irrespective of how I run the job queue.

I was able to reproduce the issue by passing wait and procs to the runJobs.php script:

php /srv/mediawiki/targets/production/maintenance/runJobs.php --wait --maxjobs=1000 --memory-limit=1G --procs=2

Though this works fine locally.

Yaron_Koren renamed this task from ReplaceText not working: TypeError: Return value of User::getName() must be of the type string, null returned to ReplaceText jobs sometimes fail when User::getName() returns null.Aug 2 2023, 10:51 PM

Change 957808 had a related patch set uploaded (by TechieNK; author: TechieNK):

[mediawiki/extensions/ReplaceText@master] Fix user existence problem

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

Can anyone here verify whether this patch fixes the problem? (Assuming it's still a problem.)

Change 957808 merged by jenkins-bot:

[mediawiki/extensions/ReplaceText@master] Fix user existence problem

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

It's merged in now - so if anyone can try the latest code and see if the underlying problem is still there or not, that would be great.