facebook/react · error · Error

input is a self-closing tag and must neither have `children`

Error message

input is a self-closing tag and must neither have `children` nor use `dangerouslySetInnerHTML`.

What it means

Thrown while serializing an <input> start tag in Fizz: the props loop hits a non-null children or dangerouslySetInnerHTML prop and throws. <input> is a void/self-closing element — HTML has no closing tag for it, so children would never be emitted and dangerouslySetInnerHTML has no target element content; React refuses rather than silently dropping them.

Source

Thrown at packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:2529

  let formAction = null;
  let formEncType = null;
  let formMethod = null;
  let formTarget = null;
  let value = null;
  let defaultValue = null;
  let checked = null;
  let defaultChecked = null;

  for (const propKey in props) {
    if (hasOwnProperty.call(props, propKey)) {
      const propValue = props[propKey];
      if (propValue == null) {
        continue;
      }
      switch (propKey) {
        case 'children':
        case 'dangerouslySetInnerHTML':
          throw new Error(
            `${'input'} is a self-closing tag and must neither have \`children\` nor ` +
              'use `dangerouslySetInnerHTML`.',
          );
        case 'name':
          name = propValue;
          break;
        case 'formAction':
          formAction = propValue;
          break;
        case 'formEncType':
          formEncType = propValue;
          break;
        case 'formMethod':
          formMethod = propValue;
          break;
        case 'formTarget':
          formTarget = propValue;
          break;

View on GitHub (pinned to eafeac097b)

Solutions

  1. Make the input self-closing: <input type="text" defaultValue={value} /> — put the value in value/defaultValue
  2. Strip children before spreading: const {children, ...rest} = props; <input {...rest} />
  3. If you were trying to prefill it, use the value or defaultValue prop instead

Example fix

// before
<input type="text">{value}</input>
<input {...props} /> {/* props.children present */}

// after
<input type="text" defaultValue={value} />
const {children, ...rest} = props;
<input {...rest} />
Defensive patterns

Strategy: type-guard

Validate before calling

const {children, dangerouslySetInnerHTML, ...inputProps} = props;
if (__DEV__ && (children != null || dangerouslySetInnerHTML != null)) {
  console.warn('<input> cannot have children or dangerouslySetInnerHTML');
}
return <input {...inputProps} />;

Type guard

type InputProps = JSX.IntrinsicElements['input'] & {children?: never; dangerouslySetInnerHTML?: never};

Prevention

When it happens

Trigger: JSX like <input type="text">{value}</input> (JSX puts the text into props.children), or <input {...props} /> where the spread object carries a children key, or setting dangerouslySetInnerHTML on an input.

Common situations: Copy-pasting a textarea/input pattern and leaving children inside; spread props from a generic Field component that includes children; HTML-to-JSX converters emitting <input>...</input>.

Related errors


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