When using gatsby-plugin-mdx with gatsby-remark-images, images written in Markdown are being wrapped in a <p> tag, which fails React's DOM nesting validation because elements like <figure> and <figcaption> (which area generated by gatsby-remark-images) are not valid with <p> tags.
Render a Markdown image:

In a Gatsby site using gatsby-plugin-mdx and gatsby-remark-images.
The image would not be nested within a paragraph tag.
The image is nested within a <p> tag, which caused DOM validation to fail:

System:
OS: macOS 10.14.5
CPU: (8) x64 Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.15.1 - ~/.nvm/versions/node/v10.15.1/bin/node
Yarn: 1.16.0 - ~/.yarn/bin/yarn
npm: 6.9.0 - ~/.nvm/versions/node/v10.15.1/bin/npm
Languages:
Python: 2.7.10 - /usr/bin/python
Browsers:
Chrome: 75.0.3770.142
Firefox: 64.0
Safari: 12.1.1
npmPackages:
gatsby: 2.8.6 => 2.8.6
gatsby-image: 2.1.2 => 2.1.2
gatsby-plugin-favicon: 3.1.6 => 3.1.6
gatsby-plugin-feed: 2.2.3 => 2.2.3
gatsby-plugin-layout: 1.0.15 => 1.0.15
gatsby-plugin-mdx: ^1.0.7 => 1.0.7
gatsby-plugin-page-creator: 2.0.13 => 2.0.13
gatsby-plugin-react-helmet: 3.0.12 => 3.0.12
gatsby-plugin-sharp: 2.1.3 => 2.1.3
gatsby-plugin-styled-components: 3.0.7 => 3.0.7
gatsby-plugin-twitter: 2.0.13 => 2.0.13
gatsby-remark-autolink-headers: 2.0.16 => 2.0.16
gatsby-remark-copy-linked-files: ^2.1.3 => 2.1.3
gatsby-remark-external-links: 0.0.4 => 0.0.4
gatsby-remark-images: 3.1.2 => 3.1.2
gatsby-source-airtable: 2.0.8 => 2.0.8
gatsby-source-filesystem: 2.0.38 => 2.0.38
gatsby-source-github: ^0.0.2 => 0.0.2
gatsby-source-wordpress: 3.0.64 => 3.0.64
gatsby-transformer-hjson: 2.1.8 => 2.1.8
gatsby-transformer-json: 2.1.11 => 2.1.11
gatsby-transformer-remark: 2.3.12 => 2.3.12
gatsby-transformer-sharp: 2.1.21 => 2.1.21
npmGlobalPackages:
gatsby-cli: 2.6.5
cc @ChristopherBiscardi @johno
This might require making sure that gatsby-remark-images is configured to show captions under images.
I'm also experiencing this issue. Only when writing an alt text in Markdown like so:

It seems like it doesn't matter if I configure showCaptions or markdownCaptions in my config, the alt text shows up anyway if it exists. But I suppose that is a separate issue!
I just stumbled over this too.
In my gatsby config i use the mdx plugin together with the remarkplugin like this:
{
resolve: 'gatsby-plugin-mdx',
options: {
defaultLayouts: {
default: require.resolve(
`${__dirname}/src/components/page/Layout.jsx`
),
},
extensions: ['.mdx', '.md'],
gatsbyRemarkPlugins: [
{
resolve: 'gatsby-remark-images',
options: {
linkImagesToOriginal: false,
showCaptions: true,
withWebp: true,
},
},
],
plugins: ['gatsby-remark-images'],
},
},
and my images are rendered with this error in the console:
Warning: validateDOMNesting(...): <figure> cannot appear as a descendant of <p>.
in figure (created by MDXCreateElement)
It renders but the error is of course annoying, is there anything I can do to get this fixed?
Maybe related to this? https://github.com/gatsbyjs/gatsby/issues/15486
I think the issue is with the plugin handling itself as discussed in the above issue. Hopefully a fix will come soon!
I am having this same issue but with the gatsby embed video or gatsby responsive iframe, one of them creates a <div>which goes inside the <p> tag for markdown. Any updates? Thanks. Can add more info if needed but essentially the same problem.
Found a workaround for the image issue, just add remark-unwrap-images:
const mdxImageWrapFix = {
resolve: `gatsby-plugin-mdx`,
options: {
plugins: [`gatsby-remark-images`],
remarkPlugins: [require('remark-unwrap-images')],
gatsbyRemarkPlugins: [
'gatsby-remark-images',
],
},
},
I guess it should be easy to adapt this plugin to embedded video and others as well.
Is there an official fix coming for this yet? I have the same problem.
{
resolve: `gatsby-plugin-mdx`,
options: {
extensions: [`.mdx`, `.md`],
gatsbyRemarkPlugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 756,
showCaptions: true,
quality: 80,
},
},
],
},
},
Warning: validateDOMNesting(...): <figure> cannot appear as a descendant of <p>.
thanks for the tip @muuvmuuv worked for me once I removed the markdownCaptions option from my gatsby-remark-images options.
I am having this same issue but with the gatsby embed video or gatsby responsive iframe, one of them creates a
<div>which goes inside the<p>tag for markdown. Any updates? Thanks. Can add more info if needed but essentially the same problem.
<div> cannot appear as a descendant of <p>Here are the current dependency line up I used to reproduce this issue:
"@mdx-js/mdx": "1.6.5",
"@mdx-js/react": "1.6.5",
"gatsby": "2.23.3",
"gatsby-plugin-mdx": "1.2.15",
"gatsby-remark-images": "3.3.10",
"remark-unwrap-images": "2.0.0",
I can also verify there is an issue @onadeem1 pointed out when MDX wraps HTML markup tags coming from gatsby-remark-embed-video with gatsby-remark-responsive-iframe. The resulting HTML becomes
<p>
<undefined>
<div class="gatsby-resp-iframe-wrapper" style="...">
<div class="embedVideo-container">
<iframe src="..." class="embedVideo-iframe" allowfullscreen="" style="...">...</iframe>
</div>
</div>
</undefined>
</p>
along with the following error on the console
Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
in div (created by MDXCreateElement)
in MDXCreateElement (created by MDXContent)
in div (created by MDXCreateElement)
in MDXCreateElement (created by MDXContent)
in undefined (created by MDXCreateElement)
in MDXCreateElement (created by MDXContent)
in p (created by MDXCreateElement)
in MDXCreateElement (created by MDXContent)
in wrapper (created by MDXCreateElement)
in MDXCreateElement (created by MDXContent)
in MDXContent (created by MDXRenderer)
in MDXRenderer (at Bodytext.js:20)
...
If I were to use the regular .md markup with gatsby-transformer-remark without MDX support, the HTML markup does not wrap <div> within <p>
<div class="gatsby-resp-iframe-wrapper" style="...">
<div class="embedVideo-container">
<iframe src="..." class="embedVideo-iframe" allowfullscreen="" style="...">...</iframe>
</div>
</div>
remark-unwrap-images does not solve the markup wrapping issue from embedded videoTried adding remark-unwrap-images as suggested by @muuvmuuv which workaround the issue Images within <figure> nested within <p> tags are invalid by unwrapping image from gatsby-remark-images. However, it does not help with the issue from gatsby-remark-embed-video as pointed out above.
Curious if remark-unwrap-images could be extended to help solve the issue with embedded video? Perhaps the official solution should really be coming out from gatsby-plugin-mdx without the need for these workarounds. Would love to help, but not sure where to start, any pointers would be grateful!
Running into a similar issue with gatsby-remark-embed-gist and gatsby-plugin-mdx
Using the config https://github.com/weirdpattern/gatsby-remark-embed-gist/issues/12 gives these errors:
Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
The tag <undefined> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
Most helpful comment
Found a workaround for the image issue, just add
remark-unwrap-images:I guess it should be easy to adapt this plugin to embedded video and others as well.