The “MathJax Retry” Error — MathJax 4.0 documentation (original) (raw)
MathJax has a large number of optional features, and not all of them are included when you load MathJax into a web page. If one of those features is needed by your code, MathJax will suspend its operations and attempt to load the needed extension for that feature. Because this process is asynchronous, MathJax must give up the CPU, wait for the needed file to load, and restart the typesetting after it has arrived.
This process is managed internally by MathJax setting up a promise for when the file is loaded, and throwing an error so that code higher up in the typesetting process can catch that error and know that it must wait for the promise to resolve before retrying the typesetting that was being performed. This is an error with the message MathJax retry.
The promise-based typesetting and conversion functions handle this retry error automatically, and incorporate waiting for the asynchronous file loading to complete into their own promises. The synchronous functions, however, can’t do that, since the retry promise would make them asynchronous. If a retry is requested during the running of one of the synchronous functions, the retry error will not be caught, and you will likely get an error report in the browser console indicating an uncaught MathJax retry error. That indicates that you may need to rewrite your code to use the promise-based functions, instead, which means your code will have to handle asynchronous typesetting, and can’t work synchronously as it stands.
If there is no promise-based version of the code you are running, then you may be able to use the following function to process the retry errors for you.
mathjax.handleRetriesFor(function)
Arguments:
- function (
()=>any()) – A function to run with retry errors being trapped. If one occurs, the function will be called again after the promise associated with the retry error’s file loading has been resolved.
Return Promise:
A promise that is resolved when the function argument completes without a retry.
From within a web page, you can obtain the mathjax variable via
const {mathjax} = MathJax._.mathjax;
For example, you might need to do something like the following:
const {mathjax} = MathJax._.mathjax; MathJax.whenReady(mathjax.handleRetriesFor(async () => { const doc = MathJax.startup.doc; const dom = doc.convert('\color{red}{x+y}'); await doc.actionPromises(); doc.clearPromises(); return dom; })).then((node) => { document.body.append(node); MathJax.startup.document.reset(); MathJax.startup.document.updateDocument(); });
The convert() call would normally throw a MathJax retry error when loading the color extension the first time it is used, but thehandleRetriesFor() call traps that and handles it, eventually typesetting the expression once the color extension has been loaded. In addition, we wait for any promises that were created during theconvert() call (e.g., the speech extension will add one that resolves when the speech has been applied to the result), and the promises are cleared. Finally, when all the promises are resolved, the .then() call runs, where the result is appended to the document, and the document CSS is updated to include any new CSS needed for the output.
Of course, it is better to insert the TeX code (with delimiters) directly into the page and call MathJax.typesetPromise()instead, but this is only meant as an example of howmathjax.handleRetriesFor() works. MathJax v4 also includesMathJax.startup.document.convertPromise() command that includes the mathjax.handleRetriesFor() already, or you could use the MathJax.tex2chtmlPromise() orMathJax.tex2svgPromise() methods, depending on the output format that you have available.
Some things that may initiate a MathJax retry error include:
- Using the
\requiremacro in TeX code - Using a macro that autoloads its definition (like
\coloror\bbox) - Using some named entities in MathML code in the conversion functions
- Generating output for characters whose data must be loaded dynamically.
- Loading of localization files for speech generation.
If you are trying to use synchronous calls, any of these situations may lead to the MathJax retry error. If you are unable to move to the promise-based calls for some reason, then your only recourse is to load any of the needed extensions before typesetting or converting the math.
To do this, be sure to include any needed TeX extensions in theload array of the loader section of your MathJax configuration. To handle the entities in MathML, add the[mml]/entities extension to the load array.
You can load all the font data up front by setting theloadAllFontFiles option to true in the startup section of your MathJax configuration. This can cause many files to be loaded, however, so should be avoided if at all possible. It is much better to move to the promise-based calls to handle this situation. If you must use loadAllFontFiles, then you may want to pick a font with less character coverage, such as mathjax-tex, the original MathJax TeX fonts that doesn’t have any dynamically loaded data, rather than the newer fonts for version 4, which have much higher coverage, and so would involve loading more files.