Page MenuHomePhabricator

Missing $wgServer in LocalSettings.php causes fatal error "Call to a member function getIP() on null"
Closed, ResolvedPublic

Description

Yesterday I made an upgrade from 1.23 to 1.35. After all steps in mw-config run correctly and the db-update was succefully finished, I got this fatal error:

Fatal error: Uncaught Error: 
Call to a member function getIP() on null in /www/htdocs/w0068779/subpages/otherfiles/dsa_wiki/includes/user/User.php:2153
Stack trace: 
#0 /wikipage/includes/session/SessionBackend.php(742): User->getName() 
#1 /wikipage/includes/session/SessionBackend.php(626): MediaWiki\Session\SessionBackend->save() 
#2 [internal function]: MediaWiki\Session\SessionBackend->MediaWiki\Session\{closure}() 
#3 /wikipage/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(96): call_user_func_array(Object(Closure), Array) 
#4 /wikipage/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(56): Wikimedia\ScopedCallback->__destruct() 
#5 /wikipage/includes/session/SessionManager.php(890): Wikimedia\ScopedCallback::consume(NULL) 
#6 /wikipage/includes/session/SessionManager.php(3 in /wikipage/includes/user/User.php on line 2153

Fatal error: Uncaught Error: 
Call to a member function getIP() on null in /wikipage/includes/user/User.php:2153 
Stack trace: 
#0 /wikipage/includes/session/SessionBackend.php(742): User->getName() 
#1 /wikipage/includes/session/SessionBackend.php(225): MediaWiki\Session\SessionBackend->save(true) 
#2 /wikipage/includes/session/SessionManager.php(478): MediaWiki\Session\SessionBackend->shutdown() 
#3 [internal function]: MediaWiki\Session\SessionManager->shutdown() 
#4 {main} thrown in /wikipage/includes/user/User.php on line 2153

My PHP version is 7.4.10 and the MySQL version is 5.7.28. The old version runs under PHP 7.0 but I updated it before I run mw-config.
I looked for other topics with similiar errors but it doesn't work. I posted it too on "Support_desk" but they send my to post it here.

Event Timeline

Aklapper renamed this task from White page / Fatal Error after upgrade and succesfully update to 1.35 to White page / Fatal Error after upgrade and succesfully update to 1.35: "Call to a member function getIP() on null".Sep 26 2020, 9:09 AM
Aklapper edited projects, added MediaWiki-User-management; removed MW-1.35-notes.
Aklapper updated the task description. (Show Details)

Out of interest, on what page do you see this?

First I see it at the index.php but if I check other pages in the wiki (articles or special pages etc), I get the same error.

Ok

The code seems to be suggesting MW can't setup the "web request"...

What webserver? How is your PHP linked/configured with the webserver? (fcgi, fpm etc?)

Not sure if it's actually a PHP 7.4 issue, but tagging incase

It's webspace from a hoster... which line from the "phpinfo" do you need?

Something like this, YMMV

Server API 	Apache 2.0 Handler

Server API FPM/FastCGI

The Screenshot is only a part of the info... I read in an other topic that it worked to set a "sys_temp_dir". I tried it yesterday but it doesn't work.

Another similar (but not quite the same) report on IRC too...

Fatal error: Uncaught Error: Call to a member function getIP() on null in /home/public_html/w/includes/user/User.php:2153 Stack trace:
#0 /home/public_html/w/includes/session/SessionBackend.php(742): User->getName()
#1 /home/public_html/w/includes/session/SessionBackend.php(626): MediaWiki\Session\SessionBackend->save()
#2 [internal function]: MediaWiki\Session\SessionBackend->MediaWiki\Session\{closure}()
#3 /home/public_html/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(96): call_user_func_array(Object(Closure), Array) 
#4 /home/public_html/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(56): Wikimedia\ScopedCallback->__destruct()
#5 /home/public_html/w/includes/session/SessionManager.php(890): Wikimedia\ScopedCallback::consume(NULL)
#6 /home/public_html/w/includes/session/SessionManager.php(220): MediaWiki\Session\SessionManager->getSessionFromInfo(Object(MediaWiki\Session\SessionInfo), Object(WebRequest))
#7 /home/public_html/ in /home/public_html/w/includes/user/User.php on line 2153

Fatal error: Uncaught Error: Call to a member function getIP() on null in /home/public_html/w/includes/user/User.php:2153 Stack trace: 
#0 /home/public_html/w/includes/session/SessionBackend.php(742): User->getName()
#1 /home/public_html/w/includes/session/SessionBackend.php(225): MediaWiki\Session\SessionBackend->save(true)
#2 /home/public_html/w/includes/session/SessionManager.php(478): MediaWiki\Session\SessionBackend->shutdown()
#3 [internal function]: MediaWiki\Session\SessionManager->shutdown()
#4 {main} thrown in /home/public_html/w/includes/user/User.php on line 2153a

And in that case, the user had a LocalSettings.php config dating back to 1.18... Using a newly generated LocalSettings did help.

So it seems to be possibly some issue related to some refactoring Tim (I think) offhand did a while ago, removing boilerplate code from LocalSettings that really shouldn't have been in there. I know it was a few years/releases ago, but when people haven't upgraded from old versions like 1.18 or 1.23.. It's not so much of a surprise that it's cropping up now.

I would have to dig up that commit (or series of commits). CC @tstarling incase he remembers offhand

In the meantime... @Archcoven Can you post a copy of your LocalSettings.php? Please remove all passwords, tokens etc (but just empty out the strings), and any other private information that might be in there. It might become fairly obvious as to what the problematic code is in LocalSettings.. And as such, this might be more of a Documentation issue than anything else

If this is the only problem, it should be enough to take the original LocalSettings from the upgrade-package and add the nessesary informations... I hope it is so easy.

Thanks!

Feel free to try too in the meantime, I'll have a proper look later. I think... offhand, it *might* be related to the inclusion of includes/DefaultSettings.php... Which I seem to remember is one of the things that was changed in previous releases

https://gist.github.com/tyteen4a03/c3f0e1b244118c64a2e52405a18b7598 is the IRC report one

<?php
# This file was automatically generated by the MediaWiki installer.
# If you make manual changes, please keep track in case you need to
# recreate them later.
#
# See includes/DefaultSettings.php for all configurable settings
# and their default values, but don't forget to make changes in _this_
# file, not there.
#
# Further documentation for configuration settings may be found at:
# http://www.mediawiki.org/wiki/Manual:Configuration_settings

# If you customize your file layout, set $IP to the directory that contains
# the other MediaWiki files. It will be used as a base to locate files.

// For debugging
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );

if( defined( 'MW_INSTALL_PATH' ) ) {
	$IP = MW_INSTALL_PATH;
} else {
	$IP = dirname( __FILE__ );
}

$path = array( $IP, "$IP/includes", "$IP/languages" );
set_include_path( implode( PATH_SEPARATOR, $path ) . PATH_SEPARATOR . get_include_path() );

require_once( "$IP/includes/DefaultSettings.php" );

# If PHP's memory limit is very low, some operations may fail.
# ini_set( 'memory_limit', '20M' );

if ( $wgCommandLineMode ) {
	if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
		die( "This script must be run from the command line\n" );
	}
}
## Uncomment this to disable output compression
# $wgDisableOutputCompression = true;

$wgSitename         = "redacted";

## The URL base path to the directory containing the wiki;
## defaults for all runtime URL paths are based off of this.
## For more information on customizing the URLs please see:
## http://www.mediawiki.org/wiki/Manual:Short_URL
$wgScriptPath = "/w";
$wgArticlePath = "/wiki/$1";
$wgScriptExtension  = ".php";
#$wgUsePathInfo = true;
## UPO means: this is also a user preference option

$wgEnableEmail      = true;
$wgEnableUserEmail  = false; # UPO

$wgEmergencyContact = "tyteen4a03@thelastcode.io";
$wgPasswordSender = "noreply@zbots.space";

$wgEnotifUserTalk = false; # UPO
$wgEnotifWatchlist = false; # UPO
$wgEmailAuthentication = true;

## Database settings
$wgDBtype           = "mysql";
$wgDBserver         = "localhost";
$wgDBname           = "redacted";
$wgDBuser           = "redacted";
$wgDBpassword       = "redacted";

# MySQL specific settings
$wgDBprefix         = "redacted_";

# MySQL table options to use during installation or update
$wgDBTableOptions   = "ENGINE=InnoDB, DEFAULT CHARSET=binary";

## Shared memory settings
$wgMainCacheType = CACHE_ACCEL;

## To enable image uploads, make sure the 'images' directory
## is writable, then set this to true:
$wgEnableUploads = true;
$wgUseImageMagick = true;

## If you use ImageMagick (or any other shell command) on a
## Linux server, this will need to be set to the name of an
## available UTF-8 locale
$wgShellLocale = "C.UTF-8";

## If you want to use image uploads under safe mode,
## create the directories images/archive, images/thumb and
## images/temp, and make them all writable. Then uncomment
## this, if it's not already uncommented:
# $wgHashedUploadDirectory = false;

## If you have the appropriate support software installed
## you can enable inline LaTeX equations:
$wgUseTeX           = false;

$wgUseInstantCommons = false;
$wgBlockDisablesLogin = true;

$wgLocalInterwiki   = strtolower($wgSitename);

$wgLanguageCode = "en";

$wgSecretKey = 'redacted';

## Default skin: you can change the default skin. Use the internal symbolic
## names, ie 'standard', 'nostalgia', 'cologneblue', 'monobook':
$wgDefaultSkin = 'vector';

## For attaching licensing metadata to pages, and displaying an
## appropriate copyright notice / icon. GNU Free Documentation
## License and Creative Commons licenses are supported so far.
# $wgEnableCreativeCommonsRdf = true;
$wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright
$wgRightsUrl = "";
$wgRightsText = "";
$wgRightsIcon = "";

// Implicit group for all visitors
$wgGroupPermissions['*']['createaccount']    = true;
$wgGroupPermissions['*']['read']             = true;
$wgGroupPermissions['*']['edit']             = false;
$wgGroupPermissions['*']['createpage']       = false;
$wgGroupPermissions['*']['createtalk']       = false;
$wgGroupPermissions['*']['writeapi']         = false;
//$wgGroupPermissions['*']['patrolmarks']      = false; // let anons see what was patrolled

// Implicit group for all logged-in accounts
$wgGroupPermissions['user']['read']             = true;
$wgGroupPermissions['user']['edit']             = true;
$wgGroupPermissions['user']['createpage']       = true;
$wgGroupPermissions['user']['createtalk']       = true;
$wgGroupPermissions['user']['writeapi']         = true;
$wgGroupPermissions['user']['upload']           = true;
$wgGroupPermissions['user']['reupload']         = true;
$wgGroupPermissions['user']['reupload-shared']  = true;
$wgGroupPermissions['user']['minoredit']        = true;
$wgGroupPermissions['user']['purge']            = true; // can use ?action=purge without clicking "ok"
$wgGroupPermissions['user']['sendemail']        = true;
$wgGroupPermissions['user']['wysiwyg'] = true;
$wgGroupPermissions['user']['oathauth-enable'] = true;
// Implicit group for accounts that pass $wgAutoConfirmAge
$wgGroupPermissions['autoconfirmed']['autoconfirmed'] = true;

// Users with bot privilege can have their edits hidden
// from various log pages by default
$wgGroupPermissions['bot']['bot']              = true;
$wgGroupPermissions['bot']['autoconfirmed']    = true;
$wgGroupPermissions['bot']['nominornewtalk']   = true;
$wgGroupPermissions['bot']['autopatrol']       = true;
$wgGroupPermissions['bot']['suppressredirect'] = true;
$wgGroupPermissions['bot']['apihighlimits']    = true;
$wgGroupPermissions['bot']['writeapi']         = true;
#$wgGroupPermissions['bot']['editprotected']    = true; // can edit all protected pages without cascade protection enabled

$wgGroupPermissions['bureaucrat']['usermerge'] = true;

// Most extra permission abilities go to this group
$wgGroupPermissions['sysop']['block']            = true;
$wgGroupPermissions['sysop']['createaccount']    = true;
$wgGroupPermissions['sysop']['delete']           = true;
$wgGroupPermissions['sysop']['bigdelete']        = true; // can be separately configured for pages with > $wgDeleteRevisionsLimit revs
$wgGroupPermissions['sysop']['deletedhistory']   = true; // can view deleted history entries, but not see or restore the text
$wgGroupPermissions['sysop']['deletedtext']      = true; // can view deleted revision text
$wgGroupPermissions['sysop']['undelete']         = true;
$wgGroupPermissions['sysop']['editinterface']    = true;
$wgGroupPermissions['sysop']['editusercss']      = true;
$wgGroupPermissions['sysop']['edituserjs']       = true;
$wgGroupPermissions['sysop']['import']           = true;
$wgGroupPermissions['sysop']['importupload']     = true;
$wgGroupPermissions['sysop']['move']             = true;
$wgGroupPermissions['sysop']['move-subpages']    = true;
$wgGroupPermissions['sysop']['move-rootuserpages'] = true;
$wgGroupPermissions['sysop']['patrol']           = true;
$wgGroupPermissions['sysop']['autopatrol']       = true;
$wgGroupPermissions['sysop']['protect']          = true;
$wgGroupPermissions['sysop']['proxyunbannable']  = true;
$wgGroupPermissions['sysop']['rollback']         = true;
$wgGroupPermissions['sysop']['upload']           = true;
$wgGroupPermissions['sysop']['reupload']         = true;
$wgGroupPermissions['sysop']['reupload-shared']  = true;
$wgGroupPermissions['sysop']['unwatchedpages']   = true;
$wgGroupPermissions['sysop']['autoconfirmed']    = true;
$wgGroupPermissions['sysop']['upload_by_url']    = true;
$wgGroupPermissions['sysop']['ipblock-exempt']   = true;
$wgGroupPermissions['sysop']['blockemail']       = true;
$wgGroupPermissions['sysop']['markbotedits']     = true;
$wgGroupPermissions['sysop']['apihighlimits']    = true;
$wgGroupPermissions['sysop']['browsearchive']    = true;
$wgGroupPermissions['sysop']['noratelimit']      = true;
$wgGroupPermissions['sysop']['movefile']         = true;
$wgGroupPermissions['sysop']['unblockself']      = true;
$wgGroupPermissions['sysop']['suppressredirect'] = true;
$wgGroupPermissions['sysop']['checkuser'] = true;
$wgGroupPermissions['sysop']['checkuser-log'] = true;
$wgGroupPermissions['sysop']['move']             = true;
$wgGroupPermissions['sysop']['move-subpages']    = true;
$wgGroupPermissions['sysop']['move-rootuserpages'] = true; // can move root userpages
$wgGroupPermissions['sysop']['deleterevision']  = true;
$wgGroupPermissions['sysop']['renameuser'] = true;
$wgGroupPermissions['sysop']['interwiki'] = true;

$wgDiff3 = "/usr/bin/diff3";

$wgShowExceptionDetails = true;
$wgCookieSetOnIpBlock = true;

# When you make changes to this configuration file, this will make
# sure that cached pages are cleared.
$wgCacheEpoch = max( $wgCacheEpoch, gmdate( 'YmdHis', @filemtime( __FILE__ ) ) );

$wgLogo = "/w/wiki.png";
$wgPFEnableStringFunctions = true;

$wgFileExtensions[] = 'svg';

# Plugins includes
// Abuse Filter
wfLoadExtension( 'AbuseFilter' );

$wgGroupPermissions['sysop']['abusefilter-modify'] = true;
$wgGroupPermissions['sysop']['abusefilter-log-detail'] = true;
$wgGroupPermissions['sysop']['abusefilter-view'] = true;
$wgGroupPermissions['sysop']['abusefilter-log'] = true;
$wgGroupPermissions['sysop']['abusefilter-privatedetails'] = true;
$wgGroupPermissions['sysop']['abusefilter-modify-restricted'] = true;
$wgGroupPermissions['sysop']['abusefilter-revert'] = true;
$wgAbuseFilterNotificationsPrivate = true; 

wfLoadExtension("AntiSpoof");
wfLoadExtension("UserMerge");

// UploadWizard

wfLoadExtension( 'UploadWizard' );
$wgExtensionFunctions[] = function() {
	$GLOBALS['wgUploadNavigationUrl'] = SpecialPage::getTitleFor( 'UploadWizard' )->getLocalURL();
	return true;
};
$wgApiFrameOptions = 'SAMEORIGIN';

# MW Bundled stuff

// ConfirmEdit
wfLoadExtensions([ 'ConfirmEdit', 'ConfirmEdit/QuestyCaptcha' ]);

$wgCaptchaQuestions =[
    'redacted' => "redacted",
    'redacted' => "redacted",
    'redacted' => "redacted",
];

//
wfLoadExtension('Cite');
wfLoadExtension('CiteThisPage');

wfLoadExtension('CategoryTree');

// WikiEditor
$wgDefaultUserOptions['wikieditor-preview'] = 1;
$wgDefaultUserOptions['wikieditor-publish'] = 1;
wfLoadExtension( 'WikiEditor' );
wfLoadExtension( 'Gadgets' );
wfLoadExtension( 'ImageMap' );
wfLoadExtension( 'InputBox' );
wfLoadExtension( 'Interwiki' );
wfLoadExtension( 'LocalisationUpdate' );
$wgLocalisationUpdateDirectory = "$IP/cache";
wfLoadExtension( 'MultimediaViewer' );
wfLoadExtension( 'Nuke' );
wfLoadExtension( 'OATHAuth' );
wfLoadExtension( 'ParserFunctions' );
wfLoadExtension( 'PdfHandler' );
wfLoadExtension( 'Poem' );
wfLoadExtension( 'Renameuser' );
wfLoadExtension( 'SpamBlacklist' );
wfLoadExtension( 'TitleBlacklist' );

// Vector skin install
wfLoadSkin("Vector");

wfLoadExtension( 'CodeEditor' );
$wgDefaultUserOptions['usebetatoolbar'] = 1; // user option provided by WikiEditor extension

// MobileFrontend
wfLoadExtension( 'MobileFrontend' );
$wgMFAutodetectMobileView = true;
wfLoadSkin( 'MinervaNeue' );
$wgMFDefaultSkinClass = "SkinMinerva";
$wgMobileFrontendLogo = $wgLogo;
$wgMFEnableBeta = true;


wfLoadExtension("ReplaceText");
wfLoadExtension( 'SecureLinkFixer' );
//wfLoadExtension( 'VisualEditor' );
wfLoadExtension( 'TemplateData' );
wfLoadExtension('PageImages');
wfLoadExtension('TextExtracts');

The same error like before after I tried the other "LocalSetting". The "DefaultSettings" I did not change because there was nothing I had to change in it...

Fatal error:
Uncaught Error: Call to a member function getIP() on null in /www/htdocs/w0068779/subpages/otherfiles/dsa_wiki/includes/user/User.php:2153
Stack trace:
#0 /wikipages/includes/session/SessionBackend.php(742): User->getName()
#1 /wikipages/includes/session/SessionBackend.php(626): MediaWiki\Session\SessionBackend->save()
#2 [internal function]: MediaWiki\Session\SessionBackend->MediaWiki\Session\{closure}()
#3 /wikipages/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(96): call_user_func_array(Object(Closure), Array)
#4 /wikipages/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(56): Wikimedia\ScopedCallback->__destruct()
#5 /wikipages/includes/session/SessionManager.php(890): Wikimedia\ScopedCallback::consume(NULL)
#6 /wikipages/includes/session/SessionManager.php(3 in /wikipages/includes/user/User.php on line 2153

Fatal error:
Uncaught Error: Call to a member function getIP() on null in /wikipages/includes/user/User.php:2153
Stack trace:
#0 /wikipages/includes/session/SessionBackend.php(742): User->getName()
#1 /wikipages/includes/session/SessionBackend.php(225): MediaWiki\Session\SessionBackend->save(true)
#2 /wikipages/includes/session/SessionManager.php(478): MediaWiki\Session\SessionBackend->shutdown()
#3 [internal function]: MediaWiki\Session\SessionManager->shutdown() #4 {main} thrown in /wikipages/includes/user/User.php on line 2153

You can definitely comment out the require/include of DefaultSettings.php from LocalSettings

I did but no change... the same error like before. Can it be a problem by changeing the URL? But in all places there is a relative path... or did I forget something?

I try to install parallel the version 1.34 from my provider and try to copy only the image-files and update the database. Maybe the result is different.

All of this isn't needed:

if( defined( 'MW_INSTALL_PATH' ) ) {
    $IP = MW_INSTALL_PATH;
} else {
    $IP = dirname( __FILE__ );
}

$path = array( $IP, "$IP/includes", "$IP/languages" );
set_include_path( implode( PATH_SEPARATOR, $path ) . PATH_SEPARATOR . get_include_path() );

require_once( "$IP/includes/DefaultSettings.php" );

if ( $wgCommandLineMode ) {
    if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
        die( "This script must be run from the command line\n" );
    }
}

Nothing changed.
I checked the database but it seems as if there are all tables correct.
And I tried to make a second install (different database, different folder) with 1.34 but there I did not get the offer to update the copied database... it overwrite all and clear the database.

Quite the same here:

Fatal error: Uncaught Error: Call to a member function getIP() on null in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php:2153
Stack trace:
#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(626): MediaWiki\Session\SessionBackend->save()
#2 [internal function]: MediaWiki\Session\SessionBackend->MediaWiki\Session\{closure}()
#3 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(96): call_user_func_array(Object(Closure), Array)
#4 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(56): Wikimedia\ScopedCallback->__destruct()
#5 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(890): Wikimedia\ScopedCallback::consume(NULL)
#6 /mnt/web309/a1/17/51913017/htdocs/updat in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php on line 2153

Fatal error: Uncaught Error: Call to a member function getIP() on null in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php:2153
Stack trace:
#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(225): MediaWiki\Session\SessionBackend->save(true)
#2 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(478): MediaWiki\Session\SessionBackend->shutdown()
#3 [internal function]: MediaWiki\Session\SessionManager->shutdown()
#4 {main}
  thrown in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php on line 2153

My environment:

  • Strato shared web hosting
  • PHP 7.3.24
  • Update from 1.28 to 1.35
  • Copied database and files before updating
  • Web Updater ran successfully without any complaints
  • Recommendations on LocalSettings.php described above did not change anything

Untagging 7.4 as it's not a 7.4 specific issue. Tagging Platform for triage and looking into as it looks to be Session/Request related

Can someone who can reproduce this please put

$wgShowExceptionDetails = true;
MWExceptionHandler::installHandler();

at the top of LocalSettings.php? The exception backtraces pasted above are truncated before they show what is really at fault.

A model I have for this is to call SessionManager::getGlobalSession() from LocalSettings.php. That generates a similar exception, with LocalSettings.php in the backtrace.

$wgRequest is initialised on Setup.php line 646, so anything that asks for a session before that point will fail with such an error. User::getName() calls User::getRequest(), which returns null when called so early.

Can someone who can reproduce this please

Sure! But the result is quite the same:

Fatal error: Uncaught Error: Call to a member function getIP() on null in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php:2153
Stack trace:
#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(626): MediaWiki\Session\SessionBackend->save()
#2 [internal function]: MediaWiki\Session\SessionBackend->MediaWiki\Session\{closure}()
#3 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(96): call_user_func_array(Object(Closure), Array)
#4 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(56): Wikimedia\ScopedCallback->__destruct()
#5 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(890): Wikimedia\ScopedCallback::consume(NULL)
#6 /mnt/web309/a1/17/51913017/htdocs/updat in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php on line 2153

Fatal error: Uncaught Error: Call to a member function getIP() on null in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php:2153
Stack trace:
#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(225): MediaWiki\Session\SessionBackend->save(true)
#2 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(478): MediaWiki\Session\SessionBackend->shutdown()
#3 [internal function]: MediaWiki\Session\SessionManager->shutdown()
#4 {main}
  thrown in /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php on line 2153

Here the initial lines of my LocalSettings.php:

<?php                                                                                                                                                                                                                                                             
error_reporting( -1 );                                                                                                                                                                                                                                            
ini_set( 'display_errors', 1 );                                                                                                                                                                                                                                   
$wgShowExceptionDetails = true;                                                                                                                                                                                                                                   
MWExceptionHandler::installHandler();

Shall I add any more settings here?

@Letsfindaway I'd like to have a proper backtrace one way or another. Let's just be direct about this. Can you apply this patch? It should show a backtrace in plain text.

diff --git a/includes/user/User.php b/includes/user/User.php
index 3da3a16511..e6159497fd 100644
--- a/includes/user/User.php
+++ b/includes/user/User.php
@@ -3109,6 +3109,12 @@ class User implements IDBAccessObject, UserIdentity {
 		}
 
 		global $wgRequest;
+		if ( !$wgRequest ) {
+			header( 'Content-Type: text/plain' );
+			print "Invalid request\n\n";
+			print ( new Exception )->getTraceAsString();
+			exit;
+		}
 		return $wgRequest;
 	}

@tstarling First of all the patch did not directly fit to the version of User.php I have. I found the only similar location at line 3202ff and inserted it there:

public function getRequest() {                                                                                                                                                                                                                            
        if ( $this->mRequest ) {                                                                                                                                                                                                                          
                return $this->mRequest;                                                                                                                                                                                                                   
        }                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                          
        global $wgRequest;                                                                                                                                                                                                                                
        if ( !$wgRequest ) {                                                                                                                                                                                                                              
                header( 'Content-Type: text/plain' );                                                                                                                                                                                                     
                print "Invalid request\n\n";                                                                                                                                                                                                              
                print ( new Exception )->getTraceAsString();                                                                                                                                                                                              
                exit;                                                                                                                                                                                                                                     
        }                                                                                                                                                                                                                                                 
        return $wgRequest;                                                                                                                                                                                                                                
}

This produced the following stack trace:

Invalid request

#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(2153): User->getRequest()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#2 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(626): MediaWiki\Session\SessionBackend->save()
#3 [internal function]: MediaWiki\Session\SessionBackend->MediaWiki\Session\{closure}()
#4 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(96): call_user_func_array(Object(Closure), Array)
#5 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/vendor/wikimedia/scoped-callback/src/ScopedCallback.php(56): Wikimedia\ScopedCallback->__destruct()
#6 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(890): Wikimedia\ScopedCallback::consume(NULL)
#7 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(334): MediaWiki\Session\SessionManager->getSessionFromInfo(Object(MediaWiki\Session\SessionInfo), Object(WebRequest))
#8 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(268): MediaWiki\Session\SessionManager->getEmptySessionInternal(Object(WebRequest))
#9 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(218): MediaWiki\Session\SessionManager->getEmptySession(Object(WebRequest))
#10 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/WebRequest.php(826): MediaWiki\Session\SessionManager->getSessionForRequest(Object(WebRequest))
#11 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(1169): WebRequest->getSession()
#12 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(338): User->loadDefaults()
#13 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(2125): User->load()
#14 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(3064): User->getId()
#15 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/UserOptionsManager.php(584): User->isRegistered()
#16 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/UserOptionsManager.php(487): MediaWiki\User\UserOptionsManager->getCacheKey(Object(User))
#17 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/UserOptionsManager.php(135): MediaWiki\User\UserOptionsManager->loadUserOptions(Object(User), 0)
#18 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(2665): MediaWiki\User\UserOptionsManager->getOption(Object(User), 'language', NULL, false)
#19 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/context/RequestContext.php(355): User->getOption('language')
#20 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/language/Message.php(404): RequestContext->getLanguage()
#21 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/language/Message.php(1304): Message->getLanguage()
#22 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/language/Message.php(862): Message->fetchMessage()
#23 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/language/Message.php(954): Message->toString('text')
#24 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWException.php(88): Message->text()
#25 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWException.php(169): MWException->msg('internalerror', 'Internal error')
#26 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWException.php(200): MWException->getPageTitle()
#27 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWException.php(231): MWException->reportHTML()
#28 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWExceptionHandler.php(104): MWException->report()
#29 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWExceptionHandler.php(185): MWExceptionHandler::report(Object(FatalError))
#30 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/exception/MWExceptionHandler.php(156): MWExceptionHandler::handleException(Object(FatalError), 'mwe_handler')
#31 [internal function]: MWExceptionHandler::handleUncaughtException(Object(FatalError))
#32 {main}Invalid request

#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(2153): User->getRequest()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#2 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(225): MediaWiki\Session\SessionBackend->save(true)
#3 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionManager.php(478): MediaWiki\Session\SessionBackend->shutdown()
#4 [internal function]: MediaWiki\Session\SessionManager->shutdown()
#5 {main}Invalid request

#0 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/user/User.php(2153): User->getRequest()
#1 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(742): User->getName()
#2 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/SessionBackend.php(215): MediaWiki\Session\SessionBackend->save(true)
#3 /mnt/web309/a1/17/51913017/htdocs/update.rosolarwiki.de/w/includes/session/Session.php(73): MediaWiki\Session\SessionBackend->deregisterSession(1)
#4 [internal function]: MediaWiki\Session\Session->__destruct()
#5 {main}

Would be happy if this can help you to identify the cause of this problem.

Martin

I was able to reproduce this by copying the LocalSettings.php supplied by @Archcoven into a MediaWiki 1.35 install. There are two problems. The first is that if a fatal error occurs early, the MW exception handler tries to start a session, causing a second fatal error, which gives the backtraces shown. The second problem is the actual fatal error, normally comprehensively hidden, but it can be seen if you patch out MWExceptionHandler:

Fatal error: Uncaught FatalError: $wgServer must be set in LocalSettings.php. See <a href="https://www.mediawiki.org/wiki/Manual:$wgServer">https://www.mediawiki.org/wiki/Manual:$wgServer</a>. in /srv/mw/reltest/includes/Setup.php:546 Stack trace: #0 /srv/mw/reltest/includes/WebStart.php(89): require_once() #1 /srv/mw/reltest/index.php(44): require('/srv/mw/reltest...') #2 {main} thrown in /srv/mw/reltest/includes/Setup.php on line 546

So the workaround is to set $wgServer in LocalSettings.php.

@Pchelolo can you comment on whether UserOptionsManager::getCacheKey() really needs to call $user->getName()? There's a lot of things wrong with this situation, but getCacheKey() is a necessary link in the chain. If I patch it as follows, the original exception is nicely displayed.

diff --git a/includes/user/UserOptionsManager.php b/includes/user/UserOptionsManager.php
index 061e814b06..1e594c8988 100644
--- a/includes/user/UserOptionsManager.php
+++ b/includes/user/UserOptionsManager.php
@@ -584,7 +584,7 @@ class UserOptionsManager extends UserOptionsLookup {
 	 * @return string
 	 */
 	private function getCacheKey( UserIdentity $user ): string {
-		return $user->isRegistered() ? "u:{$user->getId()}" : "anon:{$user->getName()}";
+		return $user->isRegistered() ? "u:{$user->getId()}" : "anon";
 	}
 
 	/**

Change 649491 had a related patch set uploaded (by Tim Starling; owner: Tim Starling):
[mediawiki/core@master] In MWExceptionHandler::report(), catch all throwables

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

https://gerrit.wikimedia.org/r/649491 fixes the issue of the original error being thrown away when a PHP catchable fatal error occurs while reporting an exception.

Change 649595 had a related patch set uploaded (by Tim Starling; owner: Tim Starling):
[mediawiki/core@master] Don't access $wgRequest from User

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

https://gerrit.wikimedia.org/r/649595 separately fixes the issue, showing a nicely formatted error message, like the UserOptionsManager pasted patch.

Change 649516 had a related patch set uploaded (by Reedy; owner: Tim Starling):
[mediawiki/core@REL1_35] In MWExceptionHandler::report(), catch all throwables

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

Change 649516 merged by jenkins-bot:
[mediawiki/core@REL1_35] In MWExceptionHandler::report(), catch all throwables

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

Change 649491 merged by jenkins-bot:
[mediawiki/core@master] In MWExceptionHandler::report(), catch all throwables

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

@Pchelolo can you comment on whether UserOptionsManager::getCacheKey() really needs to call $user->getName()? There's a lot of things wrong with this situation, but getCacheKey() is a necessary link in the chain. If I patch it as follows, the original exception is nicely displayed.

diff --git a/includes/user/UserOptionsManager.php b/includes/user/UserOptionsManager.php
index 061e814b06..1e594c8988 100644
--- a/includes/user/UserOptionsManager.php
+++ b/includes/user/UserOptionsManager.php
@@ -584,7 +584,7 @@ class UserOptionsManager extends UserOptionsLookup {
 	 * @return string
 	 */
 	private function getCacheKey( UserIdentity $user ): string {
-		return $user->isRegistered() ? "u:{$user->getId()}" : "anon:{$user->getName()}";
+		return $user->isRegistered() ? "u:{$user->getId()}" : "anon";
 	}
 
 	/**

That should work fine actually.

Change 649650 had a related patch set uploaded (by Ppchelko; owner: Ppchelko):
[mediawiki/core@master] UserOptionsManager: don't differentiate anons caches.

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

User::getName() has:

		if ( $this->mName === false ) {
			// Clean up IPs
			$this->mName = IPUtils::sanitizeIP( $this->getRequest()->getIP() );
		}

This seems dubious. Do we know that there will always be a Request object? I guess we set up fake Requests in maintenance scripts and jobs, but I'd rather that we don't make assumptions.

A user with no ID and no name should be fall back to using 'Unknown user' as the name (which is reserved per $wgReservedUsernames).

Also, falling back to global state should be avoided. Anon users with a fake "name" should be set up explicitly during initialization. Creating a User instance with new User() and then having it magically take on the current request's IP as a name is icky hidden information flow.

Change 649693 had a related patch set uploaded (by Reedy; owner: Ppchelko):
[mediawiki/core@REL1_35] UserOptionsManager: don't differentiate anons caches.

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

User::getName() has:

		if ( $this->mName === false ) {
			// Clean up IPs
			$this->mName = IPUtils::sanitizeIP( $this->getRequest()->getIP() );
		}

This seems dubious. Do we know that there will always be a Request object? I guess we set up fake Requests in maintenance scripts and jobs, but I'd rather that we don't make assumptions.

$wgRequest is unconditionally set in Setup.php, so yes, there is always a request, as long as you ask for one late enough.

A user with no ID and no name should be fall back to using 'Unknown user' as the name (which is reserved per $wgReservedUsernames).

That would certainly be a simple way to implement IP masking. Just attribute all anonymous edits to "Unknown user". But it seems orthogonal.

Also, falling back to global state should be avoided.

No kidding, but falling back to the global state is the documented behaviour of the User class, and many things rely on it. Again, it seems like a topic for a separate task. I've found three independent ways to fix this bug, which seems like enough.

Change 649650 merged by jenkins-bot:
[mediawiki/core@master] UserOptionsManager: don't differentiate anons caches.

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

Change 649693 merged by jenkins-bot:
[mediawiki/core@REL1_35] UserOptionsManager: don't differentiate anons caches.

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

Change 649595 merged by jenkins-bot:
[mediawiki/core@master] Don't access $wgRequest from User

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

tstarling renamed this task from White page / Fatal Error after upgrade and succesfully update to 1.35: "Call to a member function getIP() on null" to Missing $wgServer in LocalSettings.php causes fatal error "Call to a member function getIP() on null".Dec 16 2020, 8:19 PM
tstarling claimed this task.

The error message will be fixed in MediaWiki 1.35.1. Regardless of that, the solution for users is to set $wgServer in LocalSettings.php.

It's possible that errors unrelated to $wgServer could be hidden by this bug. Applying the patch should show the actual error message.