facebook/react · error · Error
Invalid tag: ${tag}
Error message
Invalid tag: ${tag} What it means
Thrown by startChunkForTag when an element's tag name fails VALID_TAG_REGEX (/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/ — start with a letter; then only letters, colons, underscores, dots, hyphens, digits). Because the tag is concatenated raw into the HTML output, this simplified XML-Name subset blocks injection of delimiters like spaces, quotes, '<', '>' or slashes; anything else aborts the render.
Source
Thrown at packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:4210
}
}
}
if (typeof children === 'string' && children[0] === '\n') {
target.push(leadingNewline);
}
return children;
}
// We accept any tag to be rendered but since this gets injected into arbitrary
// HTML, we want to make sure that it's a safe tag.
// http://www.w3.org/TR/REC-xml/#NT-Name
const VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
const validatedTagCache = new Map<string, PrecomputedChunk>();
function startChunkForTag(tag: string): PrecomputedChunk {
let tagStartChunk = validatedTagCache.get(tag);
if (tagStartChunk === undefined) {
if (!VALID_TAG_REGEX.test(tag)) {
throw new Error(`Invalid tag: ${tag}`);
}
tagStartChunk = stringToPrecomputedChunk('<' + tag);
validatedTagCache.set(tag, tagStartChunk);
}
return tagStartChunk;
}
export const doctypeChunk: PrecomputedChunk =
stringToPrecomputedChunk('<!DOCTYPE html>');
import {doctypeChunk as DOCTYPE} from 'react-server/src/ReactFizzConfig';
export function pushStartInstance(
target: Array<Chunk | PrecomputedChunk>,
type: string,
props: Object,
resumableState: ResumableState,View on GitHub (pinned to eafeac097b)
Solutions
- Validate/normalize the tag before createElement: fall back to 'div' or 'span' for names failing /^[a-zA-Z][a-zA-Z:_\-.\d]*$/
- Fix the producer of the name (strip namespaces, whitespace, angle brackets) at the data boundary
- For custom elements, ensure the name matches the Custom Elements spec (lowercase, contains a hyphen, starts with a letter)
Example fix
// before const Tag = cmsData.tagName; // e.g. "42-card" or "div class=x" < createElement(Tag, props) / > // after const TAG_RE = /^[a-zA-Z][a-zA-Z:_\-.\d]*$/; const Tag = TAG_RE.test(cmsData.tagName) ? cmsData.tagName : 'div'; React.createElement(Tag, props)
Defensive patterns
Strategy: validation
Validate before calling
const VALID_TAG = /^[a-zA-Z][a-zA-Z:_\-.\d]*$/;
function safeTag(tag: string, fallback: string = 'div'): string {
return typeof tag === 'string' && VALID_TAG.test(tag) ? tag : fallback;
}
// React.createElement(safeTag(cms.tagName), props) Type guard
function isValidElementTag(tag: unknown): tag is string {
return typeof tag === 'string' && /^[a-zA-Z][a-zA-Z:_\-.\d]*$/.test(tag);
} Prevention
- Never pass unvalidated external strings as element types; whitelist known tags
- Normalize CMS/user-derived tag names (trim, strip namespaces/attributes) at the data boundary
- Remember the rule: first char a letter; remaining chars letters, digits, ':', '_', '-', '.'
When it happens
Trigger: React.createElement with a non-static tag string: tags starting with a digit (custom element '42-card'), containing spaces/slashes/quotes, empty or undefined-as-string tags, or user/CMS-supplied tag names interpolated into JSX: <[tag] /> via createElement(tag, props).
Common situations: Dynamic tag names from CMS data or markdown renderers; custom elements built from generated identifiers; template literals producing 'div extra' or 'a/b'; passing a component variable that is actually undefined so it coerces weirdly.
Related errors
- React has blocked a javascript: URL as a security precaution
- Bridge event names must be non-empty strings.
- File/Blob fields are not yet supported in progressive forms.
- Can only set one of `children` or `props.dangerouslySetInner
- `props.dangerouslySetInnerHTML` must be in the form `{__html
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/99ff3d05b9d98857.
Report an issue: GitHub.