Page MenuHomePhabricator

Some system users have invalid 'actor' database rows
Open, Needs TriagePublic

Description

Impact

Maintenance scripts and jobs that act on behalf of a system username (such as Redirect fixer, and Global rename script) are not working or not working correctly because User::newFromName returns a named anonymous user instead of a system user.

$ mwscript fixDoubleRedirects.php --wiki labswiki

MWException: User::addToDatabase: hit a key conflict attempting to insert user 'Unknown user' row, […]
 from line 2798 of /srv/mediawiki/php-1.40.0-wmf.17/includes/user/User.php  

This currently affects 1844 accounts over 952 different wikis. Full dump at P42930,

Example
$ mwscript sql.php --wiki labswiki
> SELECT * FROM user WHERE user_name='Redirect fixer';
  [user_id] => 31136
  [user_name] => Redirect fixer
  [user_editcount] => 24
  […]

$ mwscript eval.php --wiki labswiki
> $user = User::newFromName( 'Redirect fixer' );
> $user->getName();
"Redirect fixer"
> $user->isItemLoaded('id');
true # wrong
> $user->getId();
0 # wrong
> $user->isRegistered();
false # wrong

> $user->addToDatabase();

MWException from line 2798 of /srv/mediawiki/php-1.40.0-wmf.17/includes/user/User.php:
User::addToDatabase: hit a key conflict attempting to insert user 'Unknown user' row, but it was not present in select!

#4 /srv/mediawiki/php-1.40.0-wmf.17/includes/jobqueue/jobs/DoubleRedirectJob.php(270): User->addToDatabase()
#5 /srv/mediawiki/php-1.40.0-wmf.17/includes/jobqueue/jobs/DoubleRedirectJob.php(175): DoubleRedirectJob->getUser()
#6 /srv/mediawiki/php-1.40.0-wmf.17/maintenance/fixDoubleRedirects.php(120): DoubleRedirectJob->run()

Note how the error appears to be for the insertion of a different username: "Unknown user".

Cause

There appear two distinct causes.

  1. User::newFromName / User::load fails to handle actor rows with a registered local name (i.e. not IP or foreign/imported name) but a NULL actor_user value instead of the local user ID.

This bug was introduced with change 525605 in 2019 when User::load handling for the loadFrom "name" case was switched from querying the user table to querying the actor table instead.

As a result, it is falling back to no-oping the load and treating it as an unregistered/anonymous user object. This results in addToDatabase() producing a fatal error as the row already exists. And during the re-try, User::loadFromDatabase similarly fails because it simultenously exists in the DB yet consistently has no user ID to find in the actor table. This is where the username gets swapped to "Unknown user".

  1. Apparently it was (or still is?) possible for the actor system to create rows for locally existent users without storing the user ID in actor_user.

This currently affects 1844 accounts over 952 different wikis. Full dump at P42930.

Event Timeline

Mentioned in SAL (#wikimedia-operations) [2023-01-06T18:13:25Z] <Krinkle> krinkle@cloudweb1003$ Run UPDATE actor SET actor_user=31136 WHERE actor_id=14640; to partially fix T326431

For the system users maybe the actor rows were broken as described in T236444#5611979 and not fixed after the code was fixed. To verify the cases, the query has to look at user_registration for the corresponding user row to not after the fix was deployed.

For non-system users it seems the same way, but the validation of the user name were not passed due to bad signs in the name, like slashes, underscore or newlines, possible very old names from imports. "Brad_" from T200055/T232451 is also listed. Special:Contributions could be broken as well (linking T2323 for completeness)

note: The system user Global rename script was fixed, see T344632#9118870 for more information.