<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/troubleshooting/</id>
  <link href="https://www.endpointdev.com/blog/tags/troubleshooting/"/>
  <link href="https://www.endpointdev.com/blog/tags/troubleshooting/" rel="self"/>
  <updated>2026-03-13T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Why Your AI Extractor Fails on .msg Emails (and How to Fix Decoding)</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2026/03/why-ai-extractor-fails-on-msg-emails-and-how-to-fix-decoding/"/>
      <id>https://www.endpointdev.com/blog/2026/03/why-ai-extractor-fails-on-msg-emails-and-how-to-fix-decoding/</id>
      <published>2026-03-13T00:00:00+00:00</published>
      <author>
        <name>Edgar Mlowe</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2026/03/why-ai-extractor-fails-on-msg-emails-and-how-to-fix-decoding/antenna-and-sky.webp&#34; alt=&#34;Against a blue sky with wispy white clouds, an old directional antenna points to the left of the camera atop a brick fireplace&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen, 2025. --&gt;
&lt;p&gt;I want to share a debugging lesson that saved me from tuning the wrong layer in an AI extraction pipeline.&lt;/p&gt;
&lt;p&gt;It started with a familiar symptom: extraction output looked inconsistent. Some rows were fine, but some had extra characters, especially accents. My first instinct was the same one most of us have: maybe the model needs prompt tuning.&lt;/p&gt;
&lt;p&gt;It turned out not to be a model problem. The root cause was upstream data integrity: decoding &lt;code&gt;.msg&lt;/code&gt; email HTML with the wrong charset.&lt;/p&gt;
&lt;h3 id=&#34;the-pattern-that-gives-it-away&#34;&gt;The pattern that gives it away&lt;/h3&gt;
&lt;p&gt;If you see this mix, think decoding first:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;output is mostly correct, but certain names and addresses look garbled&lt;/li&gt;
&lt;li&gt;problems appear only for some senders or date ranges&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.eml&lt;/code&gt; looks stable, but &lt;code&gt;.msg&lt;/code&gt; is inconsistent&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A classic sign looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;expected: &lt;code&gt;Müller&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;corrupted: &lt;code&gt;MÃ¼ller&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the time your extractor sees that text, the meaning is already damaged.&lt;/p&gt;
&lt;h3 id=&#34;why-msg-bites-harder-than-eml&#34;&gt;Why &lt;code&gt;.msg&lt;/code&gt; bites harder than &lt;code&gt;.eml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Quick definitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.eml&lt;/code&gt; is the standard MIME email format and usually includes charset metadata per part.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.msg&lt;/code&gt; is an Outlook container format (MAPI), where body bytes and encoding hints can be stored separately.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That difference matters.&lt;/p&gt;
&lt;p&gt;If your code assumes UTF-8 for &lt;code&gt;.msg&lt;/code&gt; HTML bytes, non-UTF messages can decode into garbage. Then downstream steps (HTML-to-PDF, OCR, LLM extraction, post-processing) just preserve and propagate bad text.&lt;/p&gt;
&lt;h3 id=&#34;the-fix-strict-explicit-controlled&#34;&gt;The fix: strict, explicit, controlled&lt;/h3&gt;
&lt;p&gt;You do not need a big rewrite. A small decode policy change can remove a whole class of silent failures. For &lt;code&gt;.msg&lt;/code&gt; HTML bytes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read the encoding hint from message metadata.&lt;/li&gt;
&lt;li&gt;Map that hint to a decoder codec.&lt;/li&gt;
&lt;li&gt;Decode in strict mode.&lt;/li&gt;
&lt;li&gt;If needed, use one controlled strict fallback.&lt;/li&gt;
&lt;li&gt;If decode still fails, fail loud.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Minimal example in Python:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;extract_msg.encoding&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; lookupCodePage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PR_INTERNET_CODEPAGE = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;3FDE0003&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;decode_msg_html_bytes&lt;/span&gt;(html_bytes: &lt;span style=&#34;color:#038&#34;&gt;bytes&lt;/span&gt;, message) -&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    codepage_id = message.getPropertyVal(PR_INTERNET_CODEPAGE)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    codec = (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lookupCodePage(codepage_id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;isinstance&lt;/span&gt;(codepage_id, &lt;span style=&#34;color:#038&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#080&#34;&gt;and&lt;/span&gt; codepage_id &amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; html_bytes.decode(codec, errors=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;strict&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;except&lt;/span&gt; (&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;LookupError&lt;/span&gt;, &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;UnicodeDecodeError&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; html_bytes.decode(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;, errors=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;strict&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;why-i-prefer-fail-loud-here&#34;&gt;Why I prefer fail-loud here&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;errors=&amp;quot;replace&amp;quot;&lt;/code&gt; keeps jobs moving, but it can hide real data corruption.&lt;/p&gt;
&lt;p&gt;For low-stakes preview features, that may be acceptable.
For transactional extraction (orders, invoices, legal, shipping), silent corruption is usually worse than an explicit failure.&lt;/p&gt;
&lt;p&gt;Use this decision rule:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Use case&lt;/th&gt;
          &lt;th&gt;Policy&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Preview/search UX&lt;/td&gt;
          &lt;td&gt;Best-effort can be acceptable with clear flags&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Transactional extraction&lt;/td&gt;
          &lt;td&gt;Strict decode + fail loud&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Mixed systems&lt;/td&gt;
          &lt;td&gt;Strict on extraction path, best-effort on preview path&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;how-to-roll-this-out-safely&#34;&gt;How to roll this out safely&lt;/h3&gt;
&lt;p&gt;Keep blast radius low:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change only the failing decode path first.&lt;/li&gt;
&lt;li&gt;Validate on a representative dataset, not one sample file.&lt;/li&gt;
&lt;li&gt;Leave unrelated paths untouched until evidence says otherwise.&lt;/li&gt;
&lt;li&gt;Expand strict policy incrementally.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This gives reliability without destabilizing the rest of the ingestion stack.&lt;/p&gt;
&lt;h3 id=&#34;observability-that-makes-this-easier-next-time&#34;&gt;Observability that makes this easier next time&lt;/h3&gt;
&lt;p&gt;Log these fields per message:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Source file&lt;/li&gt;
&lt;li&gt;Content source used (HTML or plain text)&lt;/li&gt;
&lt;li&gt;Whether encoding hint was found&lt;/li&gt;
&lt;li&gt;Selected codec&lt;/li&gt;
&lt;li&gt;Whether fallback was used&lt;/li&gt;
&lt;li&gt;Result of decoding (success, fallback, manual review, fail)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this, “random extraction quality” turns into a clear ingestion signal.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>MediaWiki extensions and wfLoadExtensionMessages</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/05/mediawiki-extensions-and/"/>
      <id>https://www.endpointdev.com/blog/2014/05/mediawiki-extensions-and/</id>
      <published>2014-05-09T00:00:00+00:00</published>
      <author>
        <name>Greg Sabino Mullane</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2014/05/mediawiki-extensions-and/image-0.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/05/mediawiki-extensions-and/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;br/&gt;&lt;small&gt;&lt;a href=&#34;https://flic.kr/p/dykcFR&#34;&gt;Image&lt;/a&gt; by &lt;a href=&#34;https://www.flickr.com/photos/yukonlife/&#34;&gt;Susan Drury&lt;/a&gt;&lt;/small&gt;
&lt;/div&gt;
&lt;p&gt;Upgrading MediaWiki can be a challenging task, especially if you use a lot of extensions.
While the core upgrade process usually goes smoothly, it’s rare you can upgrade a major
version or two without having to muddle with your collection of extensions. Extensions are bits of code that extend what MediaWiki can do. Only a few are packaged with and maintained alongside MediaWiki itself—​the great majority are written by third-party developers. When the MediaWiki API changes, it is up to those developers to update their extension so it works with the new version of MediaWiki. This does not always happen. Take for example one of the more common errors seen on a MediaWiki upgrade since 1.21 was released:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[Tue May 06 11:21:52 2014] [error] [client 12.34.56.78] PHP Fatal error:  Call to undefined function wfLoadExtensionMessages() in /home/beckett/mediawiki/extensions/PdfExport/PdfExport.php on line 83, referer: http://test.ziggy.com/wiki/Main_Page&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is because the &lt;strong&gt;wfLoadExtensionMessages&lt;/strong&gt; function, which many extensions use, has
been deprecated since MediaWiki version 1.16 and was finally removed in 1.21, resulting in the
error seen above. Luckily, this function has been a no-op since 1.16, so it is safe
to comment it out and/or make a dummy function in your LocalSettings.php file (see below).&lt;/p&gt;
&lt;p&gt;Sadly, the release notes for 1.21 make no mention of
&lt;a href=&#34;https://lists.gt.net/wiki/wikitech/214619&#34;&gt;this fairly major change&lt;/a&gt;. Let’s
walk through as if we didn’t know anything about it and see how we could solve the
given error with the help of git. For this example, we’ll use the
&lt;a href=&#34;https://www.mediawiki.org/wiki/Extension:Pdf_Export&#34;&gt;Pdf Export extension&lt;/a&gt;,
which allows you to export your wiki pages into PDF form. A pretty handy extension, and
one which completely fails to work in MediaWiki version 1.21 or better.&lt;/p&gt;
&lt;p&gt;First, let’s verify that wfLoadExtensionMessages does not exist at all in version 1.21 of MediaWiki. For
these examples, I’ve checked out the MediaWiki code via git, and am relying on
the fact that lightweight git tags were made for all the versions we are interested in.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git clone https://github.com/SemanticMediaWiki/SemanticMediaWiki.git mediawiki
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cd mediawiki
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git grep wfLoadExtensionMessages 1.21.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.21.0:HISTORY:* (bug 12880) wfLoadExtensionMessages does not use $fallback from MessagesXx.php&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A nice feature of &lt;code&gt;git grep&lt;/code&gt; is the ability to simply use a tag after the search string. In this
case, we see that the only mention of wfLoadExtensionMessages in the entire codebase is an
old mention of it in the history file. Let’s see what version that bug is from:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git grep -n wfLoadExtensionMessages 1.21.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.21.0:HISTORY:5280:* (bug 12880) wfLoadExtensionMessages does not use $fallback from MessagesXx.php
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git show 1.21.0:HISTORY | head -5280 | tac | grep &amp;#39;===&amp;#39; -m1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;=== Bug fixes in 1.12 ===&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That message is from way back in version 1.12, and doesn’t concern us. Let’s take a look at
what tags exist in the 1.20 branch so we can scan the latest one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git tag | grep &amp;#39;^1\.20&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.0rc1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.0rc2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can peek inside version 1.20.8 and see what that function did before it was removed.
By using the -A and -B (after and before) arguments to grep, we can see the entire function in
context:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git grep wfLoadExtensionMessages 1.20.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.0:HISTORY:* (bug 12880) wfLoadExtensionMessages does not use $fallback from MessagesXx.php
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.20.0:includes/GlobalFunctions.php:function wfLoadExtensionMessages() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git show 1.20.8:includes/GlobalFunctions.php | grep -B6 -A2 LoadExtensionMessages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; * Load an extension messages file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; * @deprecated since 1.16, warnings in 1.18, remove in 1.20
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; * @codeCoverageIgnore
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; */
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;function wfLoadExtensionMessages() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wfDeprecated( __FUNCTION__, &amp;#39;1.16&amp;#39; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Thus wfLoadExtensionMessages was basically a no-op in MediaWiki version 1.20, with the caveat that it will write
a deprecation warning to your error log (or, in modern versions, the debug log unless $wgDevelopmentWarnings is set).
Next we want to find the last time this function did something useful—​which should be version 1.15 according to
the comment above. Thus:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git show 1.15.0:includes/GlobalFunctions.php | grep -A4 LoadExtensionMessages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;function wfLoadExtensionMessages( $extensionName, $langcode = false ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    global $wgExtensionMessagesFiles, $wgMessageCache, $wgLang, $wgContLang;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #For recording whether extension message files have been loaded in a given language.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    static $loaded = array();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, it’s a pretty safe bet that unless you are upgrading from 1.15.0 or earlier, it should
be completely safe to remove it. When was 1.16.0 released? There are no dates in the HISTORY
file (shame), but the date it was tagged should be a good guess:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git show 1.16.0 | grep -m1 Date
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date:   Wed Jul 28 07:11:03 2010 +0000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So what should you do with extensions that are still using this deprecated function? There are
two quick solutions: comment it out inside the extension, or add a dummy function to your version
of MediaWiki.&lt;/p&gt;
&lt;p&gt;Changing the extension itself is certainly quick and easy. To get the PdfExport extension to work,
we only have to comments out two calls to wfLoadExtensionMessages inside of the file
PdfExport.php, and one inside of PdfExport_body.php. The diff:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git difftool -y -x &amp;#34;diff -u1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- /tmp/7YqvXv_PdfExport.php 2014-05-08 12:45:03 -0400
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++ PdfExport.php             2014-05-08 12:34:39 -0400
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -82,3 +82,3 @@
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   if ($img_page &amp;gt; 0 || $img_page === false) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-        wfLoadExtensionMessages(&amp;#39;PdfPrint&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+        //wfLoadExtensionMessages(&amp;#39;PdfPrint&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                $nav_urls[&amp;#39;pdfprint&amp;#39;] = array(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -92,3 +92,3 @@
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; function wfSpecialPdfToolbox (&amp;amp;$monobook) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-          wfLoadExtensionMessages(&amp;#39;PdfPrint&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+          //wfLoadExtensionMessages(&amp;#39;PdfPrint&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           if (isset($monobook-&amp;gt;data[&amp;#39;nav_urls&amp;#39;][&amp;#39;pdfprint&amp;#39;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- /tmp/7gO8Hz_PdfExport_body.php   2014-05-08 12:45:03 -0400
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++ PdfExport_body.php               2014-05-08 12:34:44 -0400
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -44,3 +44,3 @@
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            // For backwards compatibility
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-             wfLoadExtensionMessages(&amp;#39;PdfPrint&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+             //wfLoadExtensionMessages(&amp;#39;PdfPrint&amp;#39;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A better way is to add a dummy function to LocalSettings.php. This ensures that any extension
we add in the future will continue to work unmodified. Just throw this at the bottom
on your LocalSettings.php:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;wfLoadExtensionMessages&lt;/span&gt;() { }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Probably the best overall solution is to not only add that to your LocalSettings.php,
but to try to get the extension changed as well. You can notify the author, or try to
fix it yourself and release a new version if the extension has been abandoned. You might
also look to see if the extension has been superseded by a different extension, as sometime
happens.&lt;/p&gt;
&lt;p&gt;While there may be other compatibility issues when upgrading MediaWiki, for some extensions
(such as PdfExport), this is the only change needed to make it work again on newer versions of MediaWiki!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Chrome, onmousemove, and MediaWiki JavaScript</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/04/chrome-onmousemove-and-mediawiki/"/>
      <id>https://www.endpointdev.com/blog/2014/04/chrome-onmousemove-and-mediawiki/</id>
      <published>2014-04-18T00:00:00+00:00</published>
      <author>
        <name>Greg Sabino Mullane</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; float: right; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2014/04/chrome-onmousemove-and-mediawiki/image-0-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/04/chrome-onmousemove-and-mediawiki/image-0.jpeg&#34;/&gt;&lt;/a&gt;
&lt;br/&gt;&lt;small&gt;&lt;a href=&#34;https://flic.kr/p/aM4L46&#34;&gt;Image&lt;/a&gt; by Flickr user &lt;a href=&#34;https://www.flickr.com/photos/archer10/&#34;&gt;Dennis Jarvis&lt;/a&gt;&lt;/small&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;tl;dr: avoid using onmousemove events with Google Chrome.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I recently fielded a complaint about not being able to select text with the mouse on a wiki running the &lt;a href=&#34;https://www.mediawiki.org/wiki/MediaWiki&#34;&gt; MediaWiki software&lt;/a&gt;. After some troubleshooting and research, I narrowed the problem down to a bug in the Chrome browser regarding the onmousemove event. The solution in this case was to tweak JavaScript to use onmouseover instead of onmousemove.&lt;/p&gt;
&lt;p&gt;The first step in troubleshooting is to duplicate the problem. In this case, the page worked fine for me in Firefox, so I tried using the same browser as the reporter: Chrome. Sure enough, I could no longer hold down the mouse button and select text on the page. Now that the browser was implicated, it was time to see what it was about this page that caused the problem.&lt;/p&gt;
&lt;p&gt;It seemed fairly unlikely that something like this would go unfixed if it was happening on the flagship MediaWiki site, Wikipedia. Sure enough, that site worked fine, I could select the text with no problem. Testing some other random sites showed no problems either. Some googling indicated others had similar problems with Chrome, and gave a bunch of workarounds for selecting the text. However, I wanted a fix, not a workaround.&lt;/p&gt;
&lt;p&gt;There were hints that JavaScript was involved, so I disabled JavaScript in Chrome, reloaded the page, and suddenly everything started working again. Call that big clue number two. The next step was to see what was different between the local MediaWiki installation and Wikipedia. The local site was a few versions behind, but I was fortuitously testing an upgrade on a test server. This showed the problem still existed on the newer version, which meant that the problem was something specific to the wiki itself.&lt;/p&gt;
&lt;p&gt;The most likely culprit was one of the many installed &lt;a href=&#34;https://www.mediawiki.org/wiki/Manual:Extensions&#34;&gt;MediaWiki extensions&lt;/a&gt;, which are small pieces of code that perform certain actions on a wiki. These often have their own JavaScript that they run, which was still the most likely problem.&lt;/p&gt;
&lt;p&gt;Then it was some basic troubleshooting. After turning JavaScript back on, I edited the LocalSettings.php file and commented out all the user-supplied extensions. This made the problem disappear again. Then I commented out half the extensions, then half again, etc., until I was able to narrow the problem down to a single extension.&lt;/p&gt;
&lt;p&gt;The extension in question, known simply as “&lt;a href=&#34;https://www.mediawiki.org/wiki/Extension:Balloons&#34;&gt;balloons&lt;/a&gt;”, has actually been removed from the MediaWiki extensions site, for “prolonged security issues with the code.” The extension allows creation of very nice looking pop up CSS “balloons” full of text. I’m guessing the concern is because the arguments for the balloons were not sanitized properly. In a public wiki, this would be a problem, but this was for a private intranet, so we were not worried about continuing to use the extension. As a side note, such changes would be caught anyway as this wiki sends an email to a few people on any change, including a full text diff of all the changes.&lt;/p&gt;
&lt;p&gt;Looking inside the JavaScript used by the extension, I was able to narrow the problem down to a single line inside balloons/js/balloons.js:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;// Track the cursor every time the mouse moves
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#038&#34;&gt;document&lt;/span&gt;.onmousemove = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.setActiveCoordinates;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sure enough, duck-duck-going through the Internet quickly found &lt;a href=&#34;https://code.google.com/p/chromium/issues/detail?id=170631&#34;&gt;a fairly incriminating Chromium bug&lt;/a&gt;, indicating that onmousemove did not work very well at all. Looking over the balloon extension code, it appeared that onmouseover would probably be good enough to gather the same information and allow the extension to work while not blocking the ability for people to select text. One small replacement of “move” to “over”, and everything was back to working as it should!&lt;/p&gt;
&lt;p&gt;So in summary, if you cannot select text with the mouse in Chrome (or you see any other odd mouse-related behaviors), suspect an onmousemove issue.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
