facebook/react · error · Error

137

137

Error message

${tag} is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.

What it means

<img> is a void element: it can never contain DOM children. In setInitialProperties' special img fast-path (which orders src/srcSet last to avoid double-fetching), any non-null children or dangerouslySetInnerHTML prop throws. The check runs before the browser-quirk handling, on the initial mount only.

Source

Thrown at packages/react-dom-bindings/src/client/ReactDOMComponent.js:1162

      for (const propKey in props) {
        if (!props.hasOwnProperty(propKey)) {
          continue;
        }
        const propValue = props[propKey];
        if (propValue == null) {
          continue;
        }
        switch (propKey) {
          case 'src':
            hasSrc = true;
            break;
          case 'srcSet':
            hasSrcSet = true;
            break;
          case 'children':
          case 'dangerouslySetInnerHTML': {
            // TODO: Can we make this a DEV warning to avoid this deny list?
            throw new Error(
              `${tag} is a void element tag and must neither have \`children\` nor ` +
                'use `dangerouslySetInnerHTML`.',
            );
          }
          // defaultChecked and defaultValue are ignored by setProp
          default: {
            setProp(domElement, tag, propKey, propValue, props, null);
          }
        }
      }
      if (hasSrcSet) {
        setProp(domElement, tag, 'srcSet', props.srcSet, props, null);
      }
      if (hasSrc) {
        setProp(domElement, tag, 'src', props.src, props, null);
      }
      return;
    }

View on GitHub (pinned to eafeac097b)

Solutions

  1. Move the content out: render <img /> self-closed and put text/caption in a sibling element
  2. Use alt (or aria-label on a wrapper) for accessible description instead of children
  3. In generic wrappers, destructure children out before spreading onto void tags: const {children, ...rest} = props; <img {...rest} />
  4. For decoration use CSS background-image instead of child content

Example fix

// before
<img src={url}>{caption}</img>

// after
<figure>
  <img src={url} alt={caption} />
  <figcaption>{caption}</figcaption>
</figure>
Defensive patterns

Strategy: validation

Validate before calling

const VOID_TAGS = new Set(['img','input','br','hr','meta','link','area','base','col','embed','source','track','wbr','param']);
function safePropsFor(tag: string, props: Record<string, unknown>) {
  if (!VOID_TAGS.has(tag)) return props;
  const {children, dangerouslySetInnerHTML, ...rest} = props;
  if (children != null || dangerouslySetInnerHTML != null) {
    console.warn(`<${tag}> is void; dropping children/html`);
  }
  return rest;
}

Type guard

const isVoidTag = (tag: string) =>
  VOID_TAGS.has(tag.toLowerCase());

Prevention

When it happens

Trigger: <img>{loader}</img> or <img {...props} /> where props contains a non-null children key; passing dangerouslySetInnerHTML on img; conditional children rendered inside an img tag.

Common situations: Copy-pasting HTML like <img>icon text</img>; component wrappers spreading arbitrary props onto img; JSX auto-inserting children via components that always render props.children inside their tag; accessibility attempts to put caption text inside the image tag.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/5d56d1a9ecf248fd. Report an issue: GitHub.