The real fix: enable Goldmark's passthrough extension
Rules 1-5 below are all workarounds for one underlying gap: by default, Hugo's
Goldmark renderer has no concept that text between \(...\) / \[...\] is math
that should be left alone. It runs its normal markdown inline parser over that
text first - catching subscript underscores next to ), }, ( as accidental
emphasis delimiters - and only hands the (already damaged) result to MathJax.
Hugo ships a built-in fix for exactly this: the passthrough extension. Add
this to your site config (config.toml / hugo.toml):
[markup]
[markup.goldmark]
[markup.goldmark.extensions]
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
Use the same delimiters you already load in math.html's MathJax config. Once
this is enabled and the site is rebuilt, Goldmark leaves everything between the
delimiters completely untouched, and most of the workarounds below become
unnecessary. Keep rules 1-5 as a fallback/diagnostic checklist for any content
still rendered without passthrough enabled (e.g. older posts, other themes, or
if passthrough is ever disabled).
Critical: your content files must use the exact same delimiter characters as
the config, or passthrough silently does nothing. Before passthrough existed,
it was common to write \\(...\\) / \\[...\\] (double backslash) in markdown,
because Goldmark's normal escape handling collapses \\ into a single \,
which happened to produce the right delimiter for MathJax by accident. Once
passthrough is enabled with the config above (single backslash: '\[', '\)',
etc.), that double-backslash source text no longer matches - the parser never
recognizes the delimiter, so it falls straight through to Goldmark's ordinary
markdown parser and you get the exact same corruption as if passthrough were
never enabled. If you enable passthrough and equations are still breaking,
first check whether your markdown source uses \\(/\\[ (double) instead of
\(/\[ (single) - a site-wide find-and-replace to single backslash is
required for passthrough to actually take effect.
Introduction
Lessons learned from debugging math rendering on my Hugo site (MathJax 3 loaded via math: true flag in the markdown files and {{ partial "math.html" . }} before the </head> tag in themes/<your-theme>/layouts/_default/baseof.html).
These are not MathJax bugs - they are Goldmark (Hugo's Markdown renderer) mangling LaTeX before MathJax ever sees it. Every fix below works around Goldmark's parsing, not MathJax's.
1. Display math must be on a single line
Broken:
\\[
\sum_{k=1}^{n} f(k) = \int_1^n f(x)\,dx
+ \frac{f(1)+f(n)}{2}
+ R_p
\\]
Goldmark can break multi-line \\[...\\] blocks - especially if a line inside looks
like a list item (starts with +, -, *, or a number followed by .). The leading
+ on its own line was read as a Markdown bullet point.
Fix: put the entire equation on one line.
\\[
\sum_{k=1}^{n} f(k) = \int_1^n f(x)\,dx + \frac{f(1)+f(n)}{2} + R_p
\\]
2. Never use literal square brackets [ ] inside an equation
Broken:
\\[ t_n = 1 + \frac{n-1}{2}[8 + (n-2) \cdot 2] \\]
Goldmark's Markdown-link parser actively scans for [...](...) patterns. A bracket
followed shortly by a parenthesis - even deep inside what is obviously a LaTeX
expression - can get misread as a link, silently corrupting or dropping the
surrounding math. This happened even when escaped with \bigl[ / \bigr], because
the characters [ and ] are still there for the Markdown tokenizer to find.
Fix: use parentheses-based delimiters instead - \Bigl( ... \Bigr),
\left( ... \right), or plain (...). Never rely on \[-escaping inside inline
contexts to protect square brackets; replace the bracket entirely.
\\[ t_n = 1 + \frac{n-1}{2}\Bigl(8 + (n-2) \cdot 2\Bigr) \\]
3. Avoid \text{...} for short labels inside superscripts/subscripts; prefer \mathrm{...}
Symptom: one equation with S_{n-1}^{\text{arith}} failed to render while a
nearly identical one with S_{n-1}^{\text{geom}} worked fine. The actual cause turned
out to be rule #2 (a bracket later in the same equation) - but \text{} nested inside
{...}^{...} is itself fragile in some Goldmark + MathJax combinations and is worth
avoiding as a precaution.
Fix: use \mathrm{...} for upright text labels in sub/superscripts when no italic
text-mode features (spacing, accents) are needed.
S_{n-1}^{\mathrm{arith}} instead of S_{n-1}^{\text{arith}}
4. Don't mix \leq, \sum, \int etc. in a long inline \(...\) expression
Broken:
\\(\int_0^n f \leq \sum_{k=1}^n f(k)\\)
Long inline expressions with multiple big operators are more likely to trip Goldmark's
inline-parsing edge cases (especially around escaping of \ sequences) than the same
expression in display mode.
Fix: promote anything with more than one "big" operator (\sum, \int, \prod,
relations like \leq/\geq combined with operators) to a display block.
\\[ \int_0^n f(x)\,dx \leq \sum_{k=1}^{n} f(k) \\]
5. Dense inline math inside a prose sentence gets corrupted, even on one line
Broken:
Section 4 below has the same two properties: the boxed identity
\\(t_n^{(\ell)} = t_1^{(\ell)} + S_{n-1}^{(\ell+1)}\\) builds each level from a seed
term plus an expansion of the level beneath it...
This looked safe by rules 1-4 above: the whole \\(...\\) span was on a single
line, had no literal [/], used no \text{}, and had no \leq/\sum/\int.
It still rendered broken - characters were silently dropped in an inconsistent
pattern (t_n became tn, S_{n-1} became S{n-1}, some ( characters vanished
while others survived). The common thread with rule 4: this expression had three
separate ^{...} / _{...} groups packed into one inline span, embedded in an
ordinary sentence Goldmark was also parsing for regular markdown syntax at the same
time.
Fix: once an inline expression has more than about two sub/superscript groups,
stop trying to keep it inline - promote it to its own display block (\\[...\\])
on its own line, and let the surrounding sentence refer to it rather than contain
it.
Section 4 below has the same two properties: its boxed identity
\\[
t_n^{(\ell)} = t_1^{(\ell)} + S_{n-1}^{(\ell+1)}
\\]
builds each level from a seed term plus an expansion of the level beneath it...
- Isolate the single equation that fails - don't try to fix the whole file at once.
- Check it against rules 1-4 above, in that order (multi-line → brackets → text-mode labels → inline complexity).
- Make ONE change at a time and re-test, since multiple suspect patterns can co-occur
in the same equation (as happened with Example 1 above: it had both
\text{}and a bracket, and the bracket was the real cause, not the text command). - Don't trust "this one rendered, that one didn't" as proof of which syntax is at fault - compare character-by-character for ALL differences, not just the obvious one.
Quick checklist before publishing any new equation
- Is the whole
\\[...\\]on one line? - Are there any literal
[or]characters? Replace with(/)or\Bigl(/\Bigr). - Any
\text{...}in a sub/superscript? Prefer\mathrm{...}. - Is a long inline
\(...\)mixing multiple big operators? Promote to display math. - Does an inline
\(...\)have more than ~2 sub/superscript groups (^{...}/_{...})? Promote to display math, even if it's all on one line.
Symmetries in Arithmetic and Geometric Series
Median Formula for Continuous Grouped Data