MathJax and "t.setAttribute is not a function"

A few months ago, I decided to write up a couple of math-heavy posts on here. I've done some minimal math markup in the past using HTML <sup> and <sub> tags, but I know that MathJax (the plugin that Wikipedia and StackOverflow use) can produce some very nice looking output, so I added it to my page. I was mostly happy with the results, although it did have an annoying insistence on centering rather than left-justifying everything. Recently, though, I got a comment on one of my MathJax-dependent posts and when I viewed it, I saw that my equations weren't rendering at all. Looking in the console, I saw:

Uncaught (in promise) TypeError: t.setAttribute is not a function
    at l.setAttribute (tex-mml-chtml.js:1)
    at e.assistiveMml (tex-mml-chtml.js:1)
    at e.assistiveMml (tex-mml-chtml.js:1)
    at r.assistiveMml (tex-mml-chtml.js:1)
    at Object.renderDoc (tex-mml-chtml.js:1)
    at v.renderDoc (tex-mml-chtml.js:1)
    at r.I.render (tex-mml-chtml.js:1)
    at tex-mml-chtml.js:1
    at e (tex-mml-chtml.js:1)
    at new Promise ()

Maybe MathJax didn't load? I checked, and I found that one of my MathJax-dependent pages loaded just fine, but the other one failed with this error. Even more confoundingly, if I downloaded the HTML and viewed it directly from my hard drive, it rendered just fine. Putting the error message into the Google casino didn't come up with much, other than an assurance that this happens to a lot of people a lot of the time.

I couldn't find any script on my site that might have been causing this; if I loaded it locally, it worked just fine, with identical page content, but if I loaded it from the web, I got a stack trace. I was loading https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js per the documentation; I tried switching over to tex-chtml.js instead but no luck. The source was minified, and I couldn't find the full source anywhere to try to debug against, either. I pretty-printed it and uploaded the pretty-printed version so I could debug against it and tried to step through to figure out where it was getting lost. Setting a logpoint yielded a clue: the function:

l.prototype.setAttribute = function(t, e, r, n) {
        return void 0 === n && (n = null),
        n ? (e = n.replace(/.*\//, "") + ":" + e.replace(/^.*:/, ""),
        t.setAttributeNS(n, e, r)) : t.setAttribute(e, r)
    }

accepts what appears to be an HTML element t, an attribute name e, an attribute value r and an optional namespace n. The failure occurred when t was an object of type Text; this makes sense, since Text elements don't have attributes. So why was a Text element being passed in here? Sure enough, when I replicated the logpoint from my local drive, only proper HTMLElement's were being passed in, hence no failure.

I set a conditional breakpoint on t instanceOf Text and found that it was breaking on this:

<span role="presentation">\</span>

... with no parent element. The full stack trace had this coming from a calling function:

r.prototype.assistiveMml = function() {
            var e, t;
            if (!this.processed.isSet("assistive-mml")) {
                try {
                    for (var r = c(this.math), n = r.next(); !n.done; n = r.next())
                        n.value.assistiveMml(this)
                } catch (t) {
                    e = {
                        error: t
                    }
                }

which was iterating over a list that contained each mathematical expression in the document — presumedly previously built by finding all instances of $$.

I finally realized what had happened - DigitalHermit added a comment outlining how to do something similar in Octave; somehow his inclusion of an example with the '\\' operator confused MathJax into failing to load. Sure enough, the MathJax documentation states:

If your [sic] are using javascript to process mathematics, and need to put a TeX or LaTeX expression in a string literal, you need to be aware that javascript uses the backslash (\) as a special character in strings. Since TeX uses the backslash to indicate a macro name, you often need backslashes in your javascript strings.

Now that I had identified the problem, there was the thornier issue of actually fixing it. I had to edit DigitalHermit's comment, but including two backslashes in a MathJax-dependent post is tricky; MathJax doesn't seem to have a clean way of handling this. The solution I finally went with was wrapping up his comment in a <code> block: MathJax ignores those.

Add a comment:

Completely off-topic or spam comments will be removed at the discretion of the moderator.

You may preserve formatting (e.g. a code sample) by indenting with four spaces preceding the formatted line(s)

Name: Name is required
Email (will not be displayed publicly):
Comment:
Comment is required
My Book

I'm the author of the book "Implementing SSL/TLS Using Cryptography and PKI". Like the title says, this is a from-the-ground-up examination of the SSL protocol that provides security, integrity and privacy to most application-level internet protocols, most notably HTTP. I include the source code to a complete working SSL implementation, including the most popular cryptographic algorithms (DES, 3DES, RC4, AES, RSA, DSA, Diffie-Hellman, HMAC, MD5, SHA-1, SHA-256, and ECC), and show how they all fit together to provide transport-layer security.

My Picture

Joshua Davies

Past Posts