Page MenuHomePhabricator

CollectionProposals.php: count(): Parameter must be an array or an object that implements Countable
Open, Needs TriagePublicPRODUCTION ERROR

Description

normalized_message
ErrorException: PHP Warning: count(): Parameter must be an array or an object that implements Countable
exception.trace
from /srv/mediawiki/php-1.36.0-wmf.32/extensions/Collection/includes/CollectionProposals.php(122)
#0 /srv/mediawiki/php-1.36.0-wmf.32/extensions/Collection/includes/CollectionProposals.php(122): MWExceptionHandler::handleError(integer, string, string, integer, array)
#1 /srv/mediawiki/php-1.36.0-wmf.32/extensions/Collection/includes/CollectionSuggest.php(202): CollectionProposals->hasBans()
#2 /srv/mediawiki/php-1.36.0-wmf.32/extensions/Collection/includes/CollectionSuggest.php(74): CollectionSuggest::getCollectionSuggestTemplate(string, string)
#3 /srv/mediawiki/php-1.36.0-wmf.32/extensions/Collection/includes/CollectionAjaxFunctions.php(187): CollectionSuggest::refresh(string, string)
#4 /srv/mediawiki/php-1.36.0-wmf.32/extensions/Collection/includes/CollectionAjaxFunctions.php(217): CollectionAjaxFunctions::onCollectionSuggestAction(string, string)
#5 /srv/mediawiki/php-1.36.0-wmf.32/includes/AjaxDispatcher.php(132): CollectionAjaxFunctions::onAjaxCollectionSuggestAddArticle(string)
#6 /srv/mediawiki/php-1.36.0-wmf.32/includes/MediaWiki.php(899): AjaxDispatcher->performAction(User)
#7 /srv/mediawiki/php-1.36.0-wmf.32/includes/MediaWiki.php(548): MediaWiki->main()
#8 /srv/mediawiki/php-1.36.0-wmf.32/index.php(53): MediaWiki->run()
#9 /srv/mediawiki/php-1.36.0-wmf.32/index.php(46): wfIndexMain()
#10 /srv/mediawiki/w/index.php(3): require(string)
#11 {main}

Details

Request ID
YDfFa8utn-KenYnHy94WdwAAABI
Request URL
https://en.wikisource.org/w/index.php

Event Timeline

dancy triaged this task as Unbreak Now! priority.Feb 25 2021, 4:01 PM
dancy created this task.

This appears to be a regressions from .31

I'm not entirely sure about this. First of all, there are no obvious candidates in .31 (at least, nothing in Collection and nothing relevant that mentions Session objects).

Also, CollectionProposals::__construct() should use a typehint on the array parameter to catch this kind of errors earlier.

That said, I think what might be happening is that Session implements ArrayAccess, which means it's not possible to use multidimensional arrays. The code is:

$session = SessionManager::getGlobalSession();
if ( !isset( $session['wsCollectionSuggestBan'] ) || $mode == 'resetbans' ) {
	$session['wsCollectionSuggestBan'] = []; // This is the property we're looking for
}

// ...
$session['wsCollectionSuggestBan'][] = $param;

// ...
$proposals = new CollectionProposals(
	$session['wsCollection'],
	$session['wsCollectionSuggestBan'], // Here we want an array
	$session['wsCollectionSuggestProp']
);

I think that line in the middle could fail with

Notice: Indirect modification of overloaded element of Foo has no effect in /in/I32hW on line 21

but I'm not finding similar notices in the logs. Also, codesearch seems to suggest that no other code is modifying 'wsCollectionSuggestBan'. I might take a closer look later.

dancy lowered the priority of this task from Unbreak Now! to Needs Triage.Feb 25 2021, 8:00 PM

Thanks for the investigation @Daimona. I would greatly appreciate that closer look.

I think that line in the middle could fail with

Notice: Indirect modification of overloaded element of Foo has no effect in /in/I32hW on line 21

Never mind, this isn't true -- Session can handle this correctly based on local tests.

Also, the stack trace shows that the $mode is 'add'. My running theory is that the session value is correctly set, but then it's unset somewhere before CollectionProposals is constructed. In particular, these are the relevant lines for the 'add' mode:

SpecialCollection::addArticleFromName( NS_MAIN, $param );
self::unban( $param );

unban() does some manipulation of that session property, but it shouldn't cause it to get unset (and it won't touch it if already unset). OTOH, SpecialCollection::addArticleFromName also does some session manipulation, and I think it might be removing the value from the session. This was another cursory look, I still need time to take a closer look to that method in SpecialCollection and its callees :-)