Docs / Troubleshooting MDX
Note: Had trouble with something that wasn’t explained here but should be? Please let us know. See § Contribute for how to help.
This article goes through several common problems and errors that might occur when using MDX. To understand how the MDX format works, we recommend that you start with § What is MDX. How to use our packages is documented in their readmes. To migrate to the latest MDX, see § Migrating from v1 to v2.
`options.renderer` is no longer supported
Incorrect `format: 'detect'`
Unexpected `format: 'detect'`
Missing `pragma` in classic runtime with `pragmaImportSource`
Unexpected deprecated option `jsxRuntime: 'classic'`, `pragma`, `pragmaFrag`, or `pragmaImportSource`
Expected `Fragment` given to `evaluate`
Expected `jsx` given to `evaluate`
Expected `jsxs` given to `evaluate`
Unexpected missing `options.baseUrl` needed…
Could not parse import/exports with acorn: $error
Unexpected `$type` in code: only import/exports are supported
Unexpected end of file in expression, expected a corresponding closing brace for `{`
Unexpected lazy line in expression in container
Could not parse expression with acorn: $error
Could not parse expression with acorn: Unexpected content after expression
Unexpected extra content in spread: only a single spread is supported
Unexpected `$type` in code: only spread elements are supported
Unexpected empty expression
Unexpected end of file $at, expected $expect
Unexpected character $at, expected $expect
Unexpected closing slash `/` in tag, expected an open tag first
Unexpected lazy line in container, expected line to be…
Unexpected attribute in closing tag, expected the end of the tag
Unexpected self-closing slash `/` in closing tag, expected the end of the tag
Unexpected closing tag `</$tag>`, expected corresponding closing tag for `<$tag>` ($at)
Cannot close `$type` ($at): a different token (`$type`, $at) is open
Cannot close document, a token (`$type`, $at) is still open
If you’re having problems integrating MDX with different tools, that’s likely due to ESM: ECMAScript modules. They’ve been in the works since 2015, we’ve supported them in MDX files from the start, and in MDX version 2 we completely switched to them. Many tools support ESM already. Most other tools are working hard to support them. Some still require extra configuration.
There’s a great Gist by @sindresorhus which explains in detail how to use ESM with many different tools. If you’re having trouble with MDX, some other tool, and ESM, you’ll likely find what you’re looking for there. Please give it a thorough read. If you’re still having problems, the issue tracker of the tools you’re integrating MDX with might provide the answer.
If you’re having trouble with tools that don’t support ESM, such as Electron, one short-term solution is to use a bundler to make a CJS version. With esbuild, this bundles the ESM package Expand example of making a CJS bundle
@mdx-js/mdx
as CJS in vendor/mdx.js
:npx esbuild @mdx-js/mdx --bundle --platform=node --outfile=vendor/mdx.js
Problems that occur when using MDX typically relate to the APIs of our packages and how to use them. Please see the documentation of the packages, functions, and options you are using for more info and examples.
`options.renderer` is no longer supported
This error is thrown by @mdx-js/loader
, our webpack loader. It was introduced in version 2 to help with migration.
The renderer
option allowed arbitrary text to be injected before each compiled MDX file. This was typically used to support frameworks other than React such as Preact. We now have options such as jsxImportSource
for that and arbitrary JavaScript can be added with recmaPlugins
. Because version 2 uses an AST based approach, it is no longer feasible to support a renderer
, so it was removed.
Please see ¶ Preact in § Getting started for how to support Preact. See ¶ Creating plugins in § Extending MDX for how to create plugins.
Incorrect `format: 'detect'`
Unexpected `format: 'detect'`
The full error message in MDX 2 is as follows:
Incorrect `format: 'detect'`: `createProcessor` can support either `md` or `mdx`; it does not support detecting the format
The full error message in MDX 3 is:
Unexpected `format: 'detect'`, which is not supported by `createProcessor`, expected `'mdx'` or `'md'`
This error is thrown by @mdx-js/mdx
, our core compiler. It was introduced in version 2 when the format
option was introduced.
The format
option, when configured with 'detect'
, allows inferring whether a file is MDX or plain markdown. Based on that information, plugins are configured differently, and with different options. This is impossible with createProcessor
and unified
.
To detect the format of passed files, please either use compile
from @mdx-js/mdx
or one of the integrations.
Missing `pragma` in classic runtime with `pragmaImportSource`
This error is thrown by @mdx-js/mdx
, our core compiler. It was introduced in version 2 when the jsxRuntime
, pragma
, and pragmaImportSource
options were introduced.
This error is thrown when jsxRuntime
is configured with 'classic'
(the default is 'automatic'
), pragmaImportSource
is defined (the default is 'react'
), but pragma
is defined as a falsey value (the default is React.createElement
).
If you are using the classic runtime, you have to define a pragma
.
Unexpected deprecated option `jsxRuntime: 'classic'`, `pragma`, `pragmaFrag`, or `pragmaImportSource`
This is a warning. It is not an error. You can keep on using these options, but expect them to be removed in the future.
All major frameworks currently support the automatic JSX runtime. The classic runtime, from MDX perspective, comes with several potential problems.
Because of that, we strongly recommend using an automatic JSX runtime and are considering removing support for the classic JSX runtime.
Expected `Fragment` given to `evaluate`
Expected `jsx` given to `evaluate`
Expected `jsxs` given to `evaluate`
These errors are thrown by @mdx-js/mdx
, our core compiler. They were introduced in version 2 when evaluate
(and evaluateSync
) were introduced.
evaluate
supports React and other frameworks. But these frameworks must support an automatic JSX runtime that exposes these three exports. If you’re getting this error, that means that either a) the framework does not support the automatic JSX runtime, or b) that you’re not passing them correctly to evaluate
.
Please see evaluate
in @mdx-js/mdx
for examples on how to pass these values.
Unexpected missing `options.baseUrl` needed…
The full error message in MDX is as follows:
Unexpected missing `options.baseUrl` needed to support `export … from`, `import`, or `import.meta.url` when generating `function-body`
This error is thrown when MDX runs that is specifically compiled with evaluate
, or with the outputFormat: 'function-body'
option to evluate somewhere later, and import.meta.url
, import
, or export … from
is used. These JavaScript features depend on a particular URL to run from, which is not available or not correct when running a function body. To solve this, pass a baseUrl
option. Likely set to import.meta.url
(or window.location.href
).
Problems that occur when writing MDX typically have relate to how to combine JS(X) and markdown. It’s an odd mix of two languages: markdown is whitespace sensitive and forgiving (what you type may not exactly work but it won’t crash) whereas JavaScript is whitespace insensitive and unforgiving (it does crash on typos).
Errors typically fall in these three categories:
<
and {
— Escape these (\<
, \{
) if you mean them as plain text instead of JS(X)Could not parse import/exports with acorn: $error
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when the keywords import
or export
are found at the start of a line but they are not followed by valid JavaScript. An example is:
import 1/1
The reason for this error is that the parser is expecting a JavaScript import or export statement. If you want the word import or export, make sure it’s not at the start of a paragraph. If you do want an import or export statement, please make sure that it’s valid JavaScript.
Unexpected `$type` in code: only import/exports are supported
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when, after an import
or export
statement, more JavaScript is found. An example is:
export const a = 1
const b = 2
The reason for this error is that we only allow import
and export
to define data. If you want to define a variable or function, please export it.
Unexpected end of file in expression, expected a corresponding closing brace for `{`
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when there is an opening curly brace not followed by a closing brace. An example is:
a { b
The reason for this error is that the parser is expecting another curly brace. If you just want a brace but not an expression, escape it: \{
. If you do want an expression, please make sure to close it with a closing brace }
. If there is a closing brace somewhere, make sure that the braces are each on their own lines with no text before the opening brace and no text after the closing brace, or that there are no blank lines between the braces.
Unexpected lazy line in expression in container
This error is thrown by our MDX parser. It was introduced in version 3. It occurs when containers with lazy lines are combined with expressions An example is:
* {1 +
2}
> {1 +
2}
The reason for this error is that the parser it likely points to a bug. Be explicit with your list items and block quotes:
* {1 +
2}
> {1 +
> 2}
Could not parse expression with acorn: $error
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when there are matching curly braces that, when interpreting what’s inside them as JavaScript, results in a syntax error. An example is:
a {const b = 'c'} d
Another example:
a {!} d
The reason for this error is that the parser is expecting a JavaScript expression. If you just want braces instead of an expression, escape the opening: \{
. If you do want an expression, make sure that it’s valid JavaScript and that it is an expression. That means statements (such as if
and else
and for
loops) do not work. If you need complex logic, you can wrap statements and whole programs into an IIFE, or move it out to a different file, export it from there, and import it in MDX.
Could not parse expression with acorn: Unexpected content after expression
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when there are matching curly braces that, and valid JavaScript is inside them, but there’s too much JavaScript. An example is:
a {'b' 'c'} d
The reason for this error is that the parser is expecting a single JavaScript expression yielding one value. If you just want braces instead of an expression, escape the opening: \{
. If you do want an expression, make sure that it yields a single value.
Unexpected extra content in spread: only a single spread is supported
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when there are multiple values spread into a JSX tag. An example is:
<div {...a, ...b} />
The reason for this error is that JSX only allows spreading a single value at a time:
<div {...a} {...b} />
Unexpected `$type` in code: only spread elements are supported
Unexpected empty expression
These errors are thrown by our MDX parser. They were introduced in version 2. They occur when something other than a spread is used in braces. An example is:
<div {values} {/* comment */} {} />
The reason for this error is that JSX only allows spreading values:
<div {...a} />
Unexpected end of file $at, expected $expect
Unexpected character $at, expected $expect
These errors are thrown by our MDX parser. They were introduced in MDX version 2. They occur when something unexpected was found in a JSX tag. Some examples are:
<
<.>
</
</.>
<a
<a?>
<a:
<a:+>
<a.
<a./>
<a b
<a b!>
<a b:
<a b:1>
<a b=
<a b=>
<a b="
<a b='
<a b={
<a/
<a/->
The reason for these errors is that JSX has a very strict grammar and expects tags to be valid. There are different solutions depending on what was expected. Please read the error message carefully as it indicates where the problem occurred and what was expected instead.
Unexpected closing slash `/` in tag, expected an open tag first
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when a closing tag is found but there are no open tags. An example is:
</div>
The reason for this error is that only open tags can be closed. You probably forgot an opening tag somewhere.
Unexpected lazy line in container, expected line to be…
This error is thrown by our MDX parser. It was introduced in version 3. It occurs when containers with lazy lines are combined with JSX. An example is:
* <x
y />
> <x
y />
The reason for this error is that the parser it likely points to a bug. Be explicit with your list items and block quotes:
* <x
y />
> <x
> y />
Unexpected attribute in closing tag, expected the end of the tag
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when attributes are placed on closing tags. An example is:
<h1>Text</h1 id="text">
The reason for this error is that only open tags can have attributes. Move these attributes to the corresponding opening tag.
Unexpected self-closing slash `/` in closing tag, expected the end of the tag
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when a closing tag is also marked as self-closing. An example is:
<h1>Text</h1/>
The reason for this error is that only opening tags can be marked as self-closing. Remove the slash after the tag name and before >
.
Unexpected closing tag `</$tag>`, expected corresponding closing tag for `<$tag>` ($at)
This error is thrown by our MDX parser. It was introduced in version 2. It occurs when a closing tag is seen that does not match the expected opening tag. An example is:
<a>Text</b>
The reason for this error is that tags must match in JSX. You likely forgot to open or close one of the two correctly.
Cannot close `$type` ($at): a different token (`$type`, $at) is open
Cannot close document, a token (`$type`, $at) is still open
This error is thrown by our MDX parser. It was introduced in version 2. It typically occurs when markdown and JSX are not interleaved correctly. An example is:
> <div>
The reason for this error is that a markdown construct ends while there are still tags open. See the rules on ¶ Interleaving in § What is MDX?