facebook/docusaurus · error · Error
${JSON.stringify(val)} is not a valid HTML tag object. "tagN
Error message
${JSON.stringify(val)} is not a valid HTML tag object. "tagName" must be defined as a string. What it means
Thrown by `assertIsHtmlTagObject` when the value IS an object but its `tagName` property is missing or not a string. This is the second-stage check after the object-shape check; it pins the failure precisely to the `tagName` field.
Source
Thrown at packages/docusaurus/src/server/htmlTags.ts:27
import htmlTags from 'html-tags';
import voidHtmlTags from 'html-tags/void';
import escapeHTML from 'escape-html';
import type {
Props,
HtmlTagObject,
HtmlTags,
LoadedPlugin,
RouterType,
} from '@docusaurus/types';
// TODO this should be done at config validation time, not here
function assertIsHtmlTagObject(val: unknown): asserts val is HtmlTagObject {
if (typeof val !== 'object' || !val) {
throw new Error(`"${val}" is not a valid HTML tag object.`);
}
const htmlTag = val as HtmlTagObject;
if (typeof htmlTag.tagName !== 'string') {
throw new Error(
`${JSON.stringify(
val,
)} is not a valid HTML tag object. "tagName" must be defined as a string.`,
);
}
if (
!htmlTag.customElement &&
!(htmlTags as string[]).includes(htmlTag.tagName)
) {
throw new Error(
`Error loading ${JSON.stringify(val)}, "${
htmlTag.tagName
}" is not a valid HTML tag. Either use a valid "tagName" or set "customElement: true".`,
);
}
}
function hashRouterAbsoluteToRelativeTagAttribute(View on GitHub (pinned to 3f483e80e3)
Solutions
- Add a string `tagName` to the object (e.g. `'meta'`, `'script'`, `'link'`).
- If constructing tags from data, validate `typeof obj.tagName === 'string'` before pushing into the array.
- Use the string-shorthand form (`'<meta .../>'`) instead of the object form for static tags.
Example fix
// before
scripts: [{attributes: {src: '/x.js'}}],
// after
scripts: [{tagName: 'script', attributes: {src: '/x.js'}}], Defensive patterns
Strategy: type-guard
Validate before calling
function assertTagsHaveName(tags: unknown[]) {
tags.forEach((t, i) => {
if (typeof t === 'object' && t !== null && typeof (t as any).tagName !== 'string') {
throw new Error(`Tag at index ${i} is missing a string tagName`);
}
});
} Type guard
function isHtmlTagObject(v: unknown): v is {tagName: string; attributes?: Record<string,string>} {
return typeof v === 'object' && v !== null && typeof (v as any).tagName === 'string';
} Prevention
- Use the `HtmlTagObject` type from `@docusaurus/types` for all tag objects.
- Prefer the string-shorthand form for static tags to avoid shape mistakes.
- Unit-test plugin tag generators before wiring into config.
When it happens
Trigger: Passing an object like `{attributes: {...}}` or `{tagName: 123}` into a tags array — i.e. an object that survived the first guard but lacks a string `tagName`. Triggered at htmlTags.ts:27 when `typeof htmlTag.tagName !== 'string'`.
Common situations: Building a tag object dynamically and forgetting the `tagName` key; renaming `tagName` to `tag` or `name`; using a numeric or symbol tagName.
Related errors
- "${val}" is not a valid HTML tag object.
- Error loading ${JSON.stringify(val)}, "${htmlTag.tagName}" i
- Unexpected "reportingSeverity" value: ${reportingSeverity}.
- ${JSON.stringify(redirect)} => Validation error: ${error.mes
- Invalid sidebars file. The document with id "${docId}" was u
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/f182b4db8977e4d8.
Report an issue: GitHub.