Page MenuHomePhabricator

Error when associating edit with event: InvalidArgumentException: Mismatching wiki ID my_wiki
Closed, ResolvedPublicBUG REPORT

Description

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

  • Find an event with contribution tracking enabled
  • Make an edit somewhere
  • When prompted, choose to associate the edit with the event

What happens?:
Association doesn't happen. Checking mw-error.log shows the following error:

my_wiki: [6211a7787db688d60cd84f88] [no req]   InvalidArgumentException: Mismatching wiki ID my_wiki
#0 /var/www/html/w/extensions/CampaignEvents/src/EventContribution/EventContributionComputeMetrics.php(120): MediaWiki\Revision\RevisionRenderer->getRenderedRevision()
#1 /var/www/html/w/extensions/CampaignEvents/src/EventContribution/EventContributionComputeMetrics.php(101): MediaWiki\Extension\CampaignEvents\EventContribution\EventContributionComputeMetrics->countInternalLinksInRevision()
#2 /var/www/html/w/extensions/CampaignEvents/src/EventContribution/EventContributionComputeMetrics.php(65): MediaWiki\Extension\CampaignEvents\EventContribution\EventContributionComputeMetrics->getInternalLinksDelta()
#3 /var/www/html/w/extensions/CampaignEvents/src/EventContribution/EventContributionJob.php(48): MediaWiki\Extension\CampaignEvents\EventContribution\EventContributionComputeMetrics->computeEventContribution()
#4 /var/www/html/w/includes/jobqueue/JobRunner.php(381): MediaWiki\Extension\CampaignEvents\EventContribution\EventContributionJob->run()
#5 /var/www/html/w/includes/jobqueue/JobRunner.php(339): MediaWiki\JobQueue\JobRunner->doExecuteJob()
#6 /var/www/html/w/includes/jobqueue/JobRunner.php(234): MediaWiki\JobQueue\JobRunner->executeJob()
#7 /var/www/html/w/maintenance/runJobs.php(107): MediaWiki\JobQueue\JobRunner->run()
#8 /var/www/html/w/maintenance/includes/MaintenanceRunner.php(696): RunJobs->execute()
#9 /var/www/html/w/maintenance/doMaintenance.php(102): MediaWiki\Maintenance\MaintenanceRunner->run()
#10 /var/www/html/w/maintenance/runJobs.php(150): require_once(string)
#11 {main}

my_wiki is the ID of the wiki where everything is happening: the event, the edit, the API request to associate the two.

I can currently reproduce this with every edit, although it's weird because it used to work until a few days ago.

What should have happened instead?:
It should go through!

Other information (browser name/version, screenshots, etc.):

The error message should really print both the revision's wiki ID AND the expected ID. I made that change locally, and it shows that while the revision has the full my_wiki, the expected value is just false (shortcut meaning "local"). I haven't verified if this is a bug in the revision backend or not.

Event Timeline

Change #1194728 had a related patch set uploaded (by Daimona Eaytoy; author: Daimona Eaytoy):

[mediawiki/core@master] Revision: use LOCAL instead of current wikiID when creating RevisionStore

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

I made a patch for core to make sure that we're consistently normalizing wiki IDs. Note, that patch alone is not enough to fix this issue: the RevisionRecord and its associated PageIdentity are loaded from the DB with LOCAL (i.e., normalized), so we can't pass the full string ID to methods such as getId, or there's going to be a mismatch there. This is fixed by the patch in CampaignEvents.

Change #1194732 had a related patch set uploaded (by Daimona Eaytoy; author: Daimona Eaytoy):

[mediawiki/extensions/CampaignEvents@master] Normalize current wiki ID to LOCAL in EventContributionComputeMetrics

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

Change #1194732 merged by jenkins-bot:

[mediawiki/extensions/CampaignEvents@master] Normalize current wiki ID to LOCAL in EventContributionComputeMetrics

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

Change #1194728 merged by jenkins-bot:

[mediawiki/core@master] Revision: use LOCAL instead of current wikiID when creating RevisionStore

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

This is working as expected now. Nice work. Marking as done / resolved.

I'm getting a stack trace on my local development Wiki since the change (I52be5f1ee59c242db6ed0efd2ecfdc380a565171):

Deprecated: Deprecated cross-wiki access to MediaWiki\Revision\RevisionRecord. Expected: 'wikidatawikidev', Actual: the local wiki. Pass expected $wikiId. [Called from MediaWiki\Revision\RevisionRecord::getId in /var/www/html/w/includes/Revision/RevisionRecord.php at line 319] in /var/www/html/w/includes/debug/MWDebug.php on line 372

In the Wikidata teams, our local setups are all cross-wiki in the sense that we're usually developing on a Wikibase Repo. This doesn't seem to affect all pages, but for sure the page I was most recently working on. Reverting to the commit in core immediately before this resolves the issue.

I'm getting a stack trace on my local development Wiki since the change (I52be5f1ee59c242db6ed0efd2ecfdc380a565171):

Deprecated: Deprecated cross-wiki access to MediaWiki\Revision\RevisionRecord. Expected: 'wikidatawikidev', Actual: the local wiki. Pass expected $wikiId. [Called from MediaWiki\Revision\RevisionRecord::getId in /var/www/html/w/includes/Revision/RevisionRecord.php at line 319] in /var/www/html/w/includes/debug/MWDebug.php on line 372

In the Wikidata teams, our local setups are all cross-wiki in the sense that we're usually developing on a Wikibase Repo. This doesn't seem to affect all pages, but for sure the page I was most recently working on. Reverting to the commit in core immediately before this resolves the issue.

Sorry about that. Could you please post a full stack trace of where that is coming from? The wfDeprecated truncated traces are unfortunately pretty useless... Assuming that wikidatawikidev is the local wiki, most likely you have code calling RevisionRecord::getId that passes the full string ID instead of the special value ::LOCAL. Sadly, I think the current format of string|false is simply too ambiguous for this exact reason, and normalization is hard to apply consistently. Long-term, T224020 would help with this (or even just my smaller proposal in T224020#11269219).

Sure:

[error] [3896f5b748556259abcd4f5b] /w/index.php?title=Special%3AEntityData%2FQ12.json&revision=7960   PHP Deprecated: Deprecated cross-wiki access to MediaWiki\Revision\RevisionRecord. Expected: 'wikidatawikidev', Actual: the local wiki. Pass expected $wikiId. [Called from MediaWiki\Revision\RevisionRecord::getId]
#0 [internal function]: MediaWiki\Exception\MWExceptionHandler::handleError()
#1 /var/www/html/w/includes/debug/MWDebug.php(372): trigger_error()
#2 /var/www/html/w/includes/debug/MWDebug.php(343): MediaWiki\Debug\MWDebug::sendRawDeprecated()
#3 /var/www/html/w/includes/GlobalFunctions.php(798): MediaWiki\Debug\MWDebug::deprecatedMsg()
#4 /var/www/html/w/includes/dao/WikiAwareEntityTrait.php(62): wfDeprecatedMsg()
#5 /var/www/html/w/includes/Revision/RevisionRecord.php(319): MediaWiki\Revision\RevisionRecord->deprecateInvalidCrossWiki()
#6 /var/www/html/w/includes/Revision/RevisionStoreRecord.php(161): MediaWiki\Revision\RevisionRecord->getId()
#7 /var/www/html/w/extensions/Wikibase/lib/includes/Store/Sql/WikiPageEntityDataLoader.php(92): MediaWiki\Revision\RevisionStoreRecord->getId()
#8 /var/www/html/w/extensions/Wikibase/lib/includes/Store/Sql/WikiPageEntityRevisionLookup.php(226): Wikibase\Lib\Store\Sql\WikiPageEntityDataLoader->loadEntityDataFromWikiPageRevision()
#9 /var/www/html/w/extensions/Wikibase/lib/includes/Store/Sql/WikiPageEntityRevisionLookup.php(111): Wikibase\Lib\Store\Sql\WikiPageEntityRevisionLookup->loadEntity()
#10 /var/www/html/w/extensions/Wikibase/lib/includes/Store/TypeDispatchingEntityRevisionLookup.php(52): Wikibase\Lib\Store\Sql\WikiPageEntityRevisionLookup->getEntityRevision()
#11 /var/www/html/w/extensions/Wikibase/data-access/src/ByTypeDispatchingEntityRevisionLookup.php(55): Wikibase\Lib\Store\TypeDispatchingEntityRevisionLookup->getEntityRevision()
#12 /var/www/html/w/extensions/Wikibase/lib/includes/Store/TypeDispatchingEntityRevisionLookup.php(52): Wikibase\DataAccess\ByTypeDispatchingEntityRevisionLookup->getEntityRevision()
#13 /var/www/html/w/extensions/Wikibase/lib/includes/Store/CachingEntityRevisionLookup.php(99): Wikibase\Lib\Store\TypeDispatchingEntityRevisionLookup->getEntityRevision()
#14 /var/www/html/w/extensions/Wikibase/lib/includes/Store/CachingEntityRevisionLookup.php(85): Wikibase\Lib\Store\CachingEntityRevisionLookup->fetchEntityRevision()
#15 /var/www/html/w/extensions/Wikibase/lib/includes/Store/CachingEntityRevisionLookup.php(99): Wikibase\Lib\Store\CachingEntityRevisionLookup->getEntityRevision()
#16 /var/www/html/w/extensions/Wikibase/lib/includes/Store/CachingEntityRevisionLookup.php(85): Wikibase\Lib\Store\CachingEntityRevisionLookup->fetchEntityRevision()
#17 /var/www/html/w/extensions/Wikibase/repo/includes/LinkedData/EntityDataRequestHandler.php(402): Wikibase\Lib\Store\CachingEntityRevisionLookup->getEntityRevision()
#18 /var/www/html/w/extensions/Wikibase/repo/includes/LinkedData/EntityDataRequestHandler.php(530): Wikibase\Repo\LinkedData\EntityDataRequestHandler->getEntityRevision()
#19 /var/www/html/w/extensions/Wikibase/repo/includes/LinkedData/EntityDataRequestHandler.php(289): Wikibase\Repo\LinkedData\EntityDataRequestHandler->showData()
#20 /var/www/html/w/extensions/Wikibase/repo/includes/Specials/SpecialEntityData.php(112): Wikibase\Repo\LinkedData\EntityDataRequestHandler->handleRequest()
#21 /var/www/html/w/includes/specialpage/SpecialPage.php(711): Wikibase\Repo\Specials\SpecialEntityData->execute()
#22 /var/www/html/w/includes/specialpage/SpecialPageFactory.php(1736): MediaWiki\SpecialPage\SpecialPage->run()
#23 /var/www/html/w/includes/actions/ActionEntryPoint.php(499): MediaWiki\SpecialPage\SpecialPageFactory->executePath()
#24 /var/www/html/w/includes/actions/ActionEntryPoint.php(143): MediaWiki\Actions\ActionEntryPoint->performRequest()
#25 /var/www/html/w/includes/MediaWikiEntryPoint.php(184): MediaWiki\Actions\ActionEntryPoint->execute()
#26 /var/www/html/w/index.php(44): MediaWiki\MediaWikiEntryPoint->run()
#27 {main}

It looks like you may have a WikiPageEntityDataLoader object for the local wiki whose $wikiID property is the full, string wiki ID (wikidatawikidev) instead of just false. Checking the instantiation in SingleEntitySourceServices, the same thing is going on with $databaseName there; the same value is used to instantiate a RevisionStore, but after my core change, the string ID is normalized to false for RevisionStore, so the two services (WikiPageEntityDataLoader and RevisionStore) are both for the local wiki, but different wiki ID formats, which later causes a mismatch. In turn, $databaseName comes from the property with the same name in DatabaseEntitySource. I found a bunch of instantiations for DatabaseEntitySource and didn't look carefully which one(s) might be relevant; however, judging from EntitySourceDefinitionsConfigParser, it looks like it can eventually come from the repoDatabase setting in entitySources. Since this is configurable, I suppose it should be normalized somewhere, turning the full string ID of the current wiki to false. I'm not sure where that should be done though. (As a minimum, you could probably do it in EntitySourceDefinitionsConfigParser when creating the DatabaseEntitySource.)

Yeah - changing repoDatabase in $entitySources to false does resolve the issue. I can do that for me (and I can let other devs know to do that), but my guess is that it's not an uncommon configuration for Wikibase users - our docs certainly don't make it clear that the value needs to be false for the local. I don't have time to work on this more today, but it might be good to get more eyes on it to see if we're going to upset a bunch of users when this change rides the train.

Yeah - changing repoDatabase in $entitySources to false does resolve the issue. I can do that for me (and I can let other devs know to do that), but my guess is that it's not an uncommon configuration for Wikibase users - our docs certainly don't make it clear that the value needs to be false for the local. I don't have time to work on this more today, but it might be good to get more eyes on it to see if we're going to upset a bunch of users when this change rides the train.

What I meant is that the code that reads repoDatabase should do something like

$repoDatabase = $sourceData['repoDatabase'];
if ( $repoDatabase === WikiMap::getCurrentWikiId() ) {
	$repoDatabase = WikiAwareEntity::LOCAL;
}

And pass that to the DatabaseEntitySource constructor, so it works regardless of what's in the local config; this mirrors the core change linked to this task. The one thing I'm not sure about is where this normalization should be applied. EntitySourceDefinitionsConfigParser seems a possible candidate, but I don't know if there's a better place.

Yeah - I also can't say what the best place is. Unfortunately, @Lucas_Werkmeister_WMDE is out today and for the next little while so I also can't get you a quick answer (and I'm signing off for today now).