User:Jon (WMF)/Edit to user or gadget script

From Meta, a Wikimedia project coordination wiki

If you are reading this it is likely that I made an edit to a script that you use and you are probably interested in why.

TLDR: Every error in your scripts is logged to a server along with the page you are viewing. Your script was either:

  • revealing information about your viewing behavior
  • logging errors in such a way that it reduces our effectiveness at tracking errors elsewhere in our software.

By fixing errors, I'm not becoming the maintainer of those scripts.

If you have any questions, please ping me on my talk page. I would also appreciate it if you helped fix the errors.

Why have I edited your page?[edit]

Wikimedia Foundation is able to track client side errors on all wikis. This allows us to see JavaScript errors that users are having.

All client side errors are treated equally which means if a gadget or user script is causing an error it can be difficult to distinguish it from errors caused by code maintained by Wikimedia engineers in our source code repositories.

There are a few cases I will edit your script

  • The script caused more than 100 errors in a single 12 hour period. It is creating noise preventing us from diagnosing more serious errors.
  • The script is throwing errors in a way that leaks information about you and undermines your privacy. Some errors occur on every single page you view. This leaks information about wiki pages that you visit. That data is private and only visible to users with the appropriate user rights. Nevertheless, I am protecting your privacy.
  • I am unable to filter out your error as a gadget in our error tracking due to the way the script is loaded. This is making it harder to diagnose other issues in the software.
  • Your user script is being used by multiple IP addresses and potentially breaking their experience.

Most of the errors that need fixing are longstanding issues. Usually we are not able to detect them until we change the code. Given the volume of errors, it is impossible to provide a personalized message on your talk page.

If you have any questions about the changes I've made, please do feel to ping me on my talk page. If you can help share the burden of these fixes I would also appreciate it.

My edit summary will list the JavaScript error that occurred, so if you feel my fix is not appropriate you should feel free to adjust accordingly to reflect how the script should behave. It is not my goal to change how features operate and my goal is to suppress errors rather than fix them. For example, a JavaScript error may warrant a user notification rather than the suppression of the error quietly.

I wrote a blog post about this initiative if you are interested. See also the diff blog.

Why didn't you fix the error?[edit]

I don't know your code! My goal is not to fix your code, but to keep the error logs for Wikimedia projects in a healthy state that allows us to identify bugs. If I think I can fix a problem in your code, I will, but more often I will do the minimum possible to suppress the error but also alert you to the problem:

  • This might result in code that calls mw.log.warn in the error state instead of throwing an error.
  • If your code is not executing at all, I might prevent further code execution with details of how to fix in an inline comment.

Why can't I do this myself?[edit]

Right now the error data is not privatized in such a way that it can be made accessible to editors, however eventually we hope to have an automated version of User:Jdlrobson/User_scripts_with_client_errors. Given we've not been tracking errors for almost a decade, there are quite a few errors in our code. Until the existing errors are at an acceptable volume, it doesn't scale to send talk page messages and wait for these errors to be fixed by maintainers for now.

Can I opt out?[edit]

Logging errors help improve our software, but if you don't care about errors, don't want us fixing scripts you maintain, or would rather not report these errors to us for privacy reason, you can opt out by adding the following code to your user common.js.

mw.loader.using('mediawiki.storage').then(function () {
  mw.storage.session.set( 'client-error-opt-out', '1' );
});

How can I avoid triggering errors?[edit]

If you edit gadgets that are enabled for anonymous users, or make edits to MediaWiki:Common.js, MediaWiki:Mobile.js or MediaWiki:Vector.js it is your responsibility to confirm you are not introducing errors. You can do this in several ways:

Lessons learned[edit]

Here I will document the common patterns I'm seeing

Use mw.log.error rather than throw[edit]

Some scripts understandably throw errors to help debug. Instead of using throw, use mw.log.error - this ensures you see the error in your JavaScript console but it is not logged to our servers.

mw.util.addPortletLink can return null[edit]

mw.util.addPortletLink can return null! Always check the result.

Legacy code[edit]

mw:ResourceLoader/Migration_guide_(users) - the majority of the issues I am seeing have been happening for several years and relate to this guide.

Code resilience relating to skin element existence[edit]

Many scripts make assumptions about certain elements being present on the page - for example

document.getElementById('#selector')

. You should always check if these elements exist in your scripts. Likewise when inserting elements into the DOM using insertBefore, check any assumptions you have about where elements are in the DOM. Just because they are there now doesn't mean they will always be!

SyntaxErrors[edit]

User scripts do not support wikitext. Using a redirect directive or adding category links will not work here. Always put such wikitext in comment blocks e.g.

// this is a comment

Global variables defined in other scripts[edit]

  • If you don't know if a variable is declared globally, it's not enough to check
    !globalVar
    . Always use
    typeof globalVar !== 'undefined'
    to check the variables existence safely.


Run scripts inside closures[edit]

User scripts are run in global scope. Without a closure this means that for users loading more than one user script it is possible to break overall execution. This is particularly a problem if your script has a common generic function name e.g. `run`

Example: https://en.wikipedia.org/w/index.php?title=User%3ADannyS712%2Fshort-tabs.js&type=revision&diff=1004922302&oldid=917076930