Page MenuHomePhabricator

Wikimedia\Assert\PreconditionException: Precondition failed: Range is not collapsed
Closed, ResolvedPublicPRODUCTION ERROR

Description

Error
normalized_message
[{reqId}] {exception_url}   Wikimedia\Assert\PreconditionException: Precondition failed: Range is not collapsed
exception.trace
from /srv/mediawiki/php-1.38.0-wmf.18/vendor/wikimedia/assert/src/Assert.php(49)
#0 /srv/mediawiki/php-1.38.0-wmf.18/extensions/DiscussionTools/includes/CommentUtils.php(525): Wikimedia\Assert\Assert::precondition(boolean, string)
#1 /srv/mediawiki/php-1.38.0-wmf.18/extensions/DiscussionTools/includes/ThreadItem.php(133): MediaWiki\Extension\DiscussionTools\CommentUtils::getRangeFirstNode(MediaWiki\Extension\DiscussionTools\ImmutableRange)
#2 /srv/mediawiki/php-1.38.0-wmf.18/extensions/DiscussionTools/includes/HeadingItem.php(109): MediaWiki\Extension\DiscussionTools\ThreadItem->getTranscludedFrom()
#3 /srv/mediawiki/php-1.38.0-wmf.18/extensions/DiscussionTools/includes/ApiDiscussionTools.php(52): MediaWiki\Extension\DiscussionTools\HeadingItem->getTranscludedFrom()
#4 /srv/mediawiki/php-1.38.0-wmf.18/includes/api/ApiMain.php(1889): MediaWiki\Extension\DiscussionTools\ApiDiscussionTools->execute()
#5 /srv/mediawiki/php-1.38.0-wmf.18/includes/api/ApiMain.php(868): ApiMain->executeAction()
#6 /srv/mediawiki/php-1.38.0-wmf.18/includes/api/ApiMain.php(839): ApiMain->executeActionWithErrorHandling()
#7 /srv/mediawiki/php-1.38.0-wmf.18/api.php(90): ApiMain->execute()
#8 /srv/mediawiki/php-1.38.0-wmf.18/api.php(45): wfApiMain()
#9 /srv/mediawiki/w/api.php(3): require(string)
#10 {main}
Impact

~45 occurrences within 45 min of deploying to group1

Notes

Details

Request URL
https://meta.wikimedia.org/w/api.php?action=discussiontools&format=*&formatversion=*&uselang=*&paction=*&page=*&oldid=*

Event Timeline

thcipriani triaged this task as Unbreak Now! priority.Jan 20 2022, 4:18 PM
thcipriani subscribed.

Adding this as a train blocker as it's:

  1. A new error with wmf.18
  2. reproducible by going to the Main Page of metawiki.
Krinkle subscribed.

It appears the DT javascript layload is making API requests on all page views. E.g. viewing pages like https://www.mediawiki.org/wiki/ResourceLoader results in an uncached and unconditional background request. That seems likely unintentional and could become a performance problem if widespread.

I'm noticing it actual talk pages as well, e.g. https://meta.wikimedia.org/wiki/User_talk:Krinkle, and for logged-out users as well, where it's making three different API queries, each one private/uncacheable.

I'm not sure what this is for and whether it's by design that this is needed during the critical path. If not, it should be defered until interaction. Otherwise, if it is critical for the initial binding of click handlers, then it seems like this information may be worth including into the page metadata directly from the server-side.

The issue occurs because some of the headings on the main page on Meta-Wiki have no content in the Parsoid HTML. This shouldn't happen.

We have some code that depends on the headings… existing, and this page is tripping this assertion.

I don't think this is likely to cause any real problems for users, and I don't think it's a train blocker. But I'll prepare a patch so that our code doesn't spam the logs.

Change 755752 had a related patch set uploaded (by Bartosz Dziewoński; author: Bartosz Dziewoński):

[mediawiki/extensions/DiscussionTools@master] Prevent assertion failure caused by empty headings

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

It appears the DT javascript layload is making API requests on all page views. E.g. viewing pages like https://www.mediawiki.org/wiki/ResourceLoader results in an uncached and unconditional background request. That seems likely unintentional and could become a performance problem if widespread.

I'm noticing it actual talk pages as well, e.g. https://meta.wikimedia.org/wiki/User_talk:Krinkle, and for logged-out users as well, where it's making three different API queries, each one private/uncacheable.

I'm not sure what this is for and whether it's by design that this is needed during the critical path. If not, it should be defered until interaction. Otherwise, if it is critical for the initial binding of click handlers, then it seems like this information may be worth including into the page metadata directly from the server-side.

It's only making those requests on discussion pages; however, on Meta-Wiki and MediaWiki.org, the main namespace is treated like a discussion page for annoying historical reasons (this was previously discussed in T291630). This is not the case on most wikis.

The API requests are not strictly needed, but pre-loading them allows the reply tool to load faster when the user actually requests it. (There's actually a TODO comment in the code to reconsider this: https://github.com/wikimedia/mediawiki-extensions-DiscussionTools/blob/7f329ca9a2a30eba79d3294d956246839c1cd705/modules/controller.js#L878-L883.) If you think this is bad, please file a bug. It doesn't seem too bad to me.


I filed T299685 about the incorrect rendering in Parsoid that triggered this problem.

Change 755752 merged by jenkins-bot:

[mediawiki/extensions/DiscussionTools@master] Prevent assertion failure caused by empty headings

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

Change 755684 had a related patch set uploaded (by Jeena Huneidi; author: Bartosz Dziewoński):

[mediawiki/extensions/DiscussionTools@wmf/1.38.0-wmf.18] Prevent assertion failure caused by empty headings

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

Change 755684 merged by jenkins-bot:

[mediawiki/extensions/DiscussionTools@wmf/1.38.0-wmf.18] Prevent assertion failure caused by empty headings

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

Mentioned in SAL (#wikimedia-operations) [2022-01-20T20:31:31Z] <jhuneidi@deploy1002> Synchronized php-1.38.0-wmf.18/extensions/DiscussionTools/includes/HeadingItem.php: Backport: [[gerrit:755684|Prevent assertion failure caused by empty headings (T299583)]] (duration: 00m 50s)

brennen subscribed.

Seeing this again in 1.39.0-wmf.2 (T300203):

Error
normalized_message
[{reqId}] {exception_url}   Wikimedia\Assert\PreconditionException: Precondition failed: Range is not collapsed
exception.trace
from /srv/mediawiki/php-1.39.0-wmf.2/vendor/wikimedia/assert/src/Assert.php(49)
#0 /srv/mediawiki/php-1.39.0-wmf.2/extensions/DiscussionTools/includes/CommentUtils.php(552): Wikimedia\Assert\Assert::precondition(boolean, string)
#1 /srv/mediawiki/php-1.39.0-wmf.2/extensions/DiscussionTools/includes/CommentUtils.php(663): MediaWiki\Extension\DiscussionTools\CommentUtils::getRangeFirstNode(MediaWiki\Extension\DiscussionTools\ImmutableRange)
#2 /srv/mediawiki/php-1.39.0-wmf.2/extensions/DiscussionTools/includes/CommentUtils.php(609): MediaWiki\Extension\DiscussionTools\CommentUtils::compareRangesAlmostEqualBoundaries(MediaWiki\Extension\DiscussionTools\ImmutableRange, MediaWiki\Extension\DiscussionTools\ImmutableRange, string)
#3 /srv/mediawiki/php-1.39.0-wmf.2/extensions/DiscussionTools/includes/CommentUtils.php(739): MediaWiki\Extension\DiscussionTools\CommentUtils::compareRanges(MediaWiki\Extension\DiscussionTools\ImmutableRange, MediaWiki\Extension\DiscussionTools\ImmutableRange)
#4 /srv/mediawiki/php-1.39.0-wmf.2/extensions/DiscussionTools/includes/ApiDiscussionToolsPreview.php(61): MediaWiki\Extension\DiscussionTools\CommentUtils::isSingleCommentSignedBy(MediaWiki\Extension\DiscussionTools\ThreadItemSet, string, Wikimedia\Parsoid\DOM\Element)
#5 /srv/mediawiki/php-1.39.0-wmf.2/includes/api/ApiMain.php(1893): MediaWiki\Extension\DiscussionTools\ApiDiscussionToolsPreview->execute()
#6 /srv/mediawiki/php-1.39.0-wmf.2/includes/api/ApiMain.php(870): ApiMain->executeAction()
#7 /srv/mediawiki/php-1.39.0-wmf.2/includes/api/ApiMain.php(841): ApiMain->executeActionWithErrorHandling()
#8 /srv/mediawiki/php-1.39.0-wmf.2/api.php(90): ApiMain->execute()
#9 /srv/mediawiki/php-1.39.0-wmf.2/api.php(45): wfApiMain()
#10 /srv/mediawiki/w/api.php(3): require(string)
#11 {main}

I made a separate task for this: T304377, because the stack trace is different. This exception is coming from the newly introduced method CommentUtils::isSingleCommentSignedBy() (added in rEDTO0ecc8a4c051d: Improve detecting already signed comments).

Also it looks like there are only 8 occurrences in total, so it doesn't seem like a train blocker.