mui/material-ui · error · Error

Expected a single child of the root

Error message

Expected a single child of the root

What it means

In the @mui/icons-material builder, an SVGO plugin (svgAsReactFragment) inspects the optimised SVG and asserts the document root has exactly one child. If the optimised SVG contains more than one top-level element (e.g. trailing whitespace nodes become elements, or two <svg> roots), the build throws. The generated icon component assumes a single <svg> root fragment child.

Source

Thrown at packages/mui-icons-material/builder.mjs:148

      { name: 'removeStyleElement' },
      { name: 'removeScripts' },
      { name: 'removeEmptyContainers' },
    ],
  });

  // True if the svg has multiple children
  let childrenAsArray = false;
  const jsxResult = svgo.optimize(result.data, {
    plugins: [
      {
        name: 'svgAsReactFragment',
        fn: () => {
          return {
            root: {
              enter(root) {
                const [svg, ...rootChildren] = root.children;
                if (rootChildren.length > 0) {
                  throw new Error('Expected a single child of the root');
                }
                if (svg.type !== 'element' || svg.name !== 'svg') {
                  throw new Error('Expected an svg element as the root child');
                }

                if (svg.children.length > 1) {
                  childrenAsArray = true;
                  svg.children.forEach((svgChild, index) => {
                    svgChild.attributes.key = index;
                    // Original name will be restored later
                    // We just need a mechanism to convert the resulting
                    // svg string into an array of JSX elements
                    svgChild.name = `SVGChild:${svgChild.name}`;
                  });
                }

                root.children = svg.children;
              },

View on GitHub (pinned to bdc96df2cb)

Solutions

  1. Open the offending SVG in an editor and ensure it has a single <svg>...</svg> root with nothing outside it (no comments, text, or second root).
  2. Re-run the SVGO optimisation manually to inspect the post-optimisation output before feeding it to the builder.
  3. If the source is generated by download.mjs, re-download the icon and check the upstream gstatic SVG.

Example fix

<!-- before: two roots -->
<svg>...</svg>
<svg>...</svg>
<!-- after -->
<svg>...</svg>
Defensive patterns

Strategy: validation

Validate before calling

import { parse } from 'svg-parser';
function hasSingleRootChild(svgString) {
  const ast = parse(svgString);
  const root = ast.children.filter(c => c.type === 'root')[0];
  return root.children.filter(c => c.type !== 'text' || c.value.trim().length > 0).length === 1;
}
// run before feeding the SVG to the builder

Prevention

When it happens

Trigger: Running the icon build/generator over an SVG source whose root has multiple element children after SVGO optimisation; corrupted/hand-edited SVG sources; an SVGO plugin config change that produces extra root nodes.

Common situations: Adding a new custom icon whose source SVG was concatenated from multiple fragments; SVGO version bump changing how comments/whitespace are preserved at the root.

Related errors


AI-assisted analysis of mui/material-ui@bdc96df2cb (2026-08-12). Data as JSON: /api/errors/b4b914e167c02aaa. Report an issue: GitHub.