facebook/lexical · error
HashtagPlugin: HashtagNode not registered on editor
Error message
HashtagPlugin: HashtagNode not registered on editor
What it means
HashtagPlugin decorates hashtag text, which only works if the editor knows the HashtagNode class; Lexical editors can only process node types listed in their nodes config. The plugin checks editor.hasNodes([HashtagNode]) inside a useEffect and throws immediately if it is missing. This catches the configuration mistake at mount time instead of failing when a hashtag is typed.
Source
Thrown at packages/lexical-react/src/LexicalHashtagPlugin.ts:28
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {type JSX, useEffect} from 'react';
/**
* Enables hashtag support by transforming runs of text that begin with `#`
* into {@link HashtagNode}s. The editor must have the {@link HashtagNode}
* registered.
*
* This is a legacy plugin. When building an editor with the extension API,
* configure {@link HashtagExtension} instead.
*
* @returns `null`, this plugin renders no DOM of its own.
*/
export function HashtagPlugin(): JSX.Element | null {
const [editor] = useLexicalComposerContext();
useEffect(() => {
if (!editor.hasNodes([HashtagNode])) {
throw new Error('HashtagPlugin: HashtagNode not registered on editor');
}
return registerLexicalHashtag(editor);
}, [editor]);
return null;
}
View on GitHub (pinned to 76a22dcba9)
Solutions
- Add HashtagNode (from @lexical/hashtag) to the editor's nodes array
- Use the hashtag extension via buildEditorFromExtensions so the node is registered
- Guard rendering: only mount HashtagPlugin when editor.hasNodes([HashtagNode]) is true
Example fix
// before
const initialConfig = {nodes: [ParagraphNode, TextNode]};
<LexicalComposer initialConfig={initialConfig}><HashtagPlugin /></LexicalComposer> // throws
// after
import {HashtagNode} from '@lexical/hashtag';
const initialConfig = {nodes: [ParagraphNode, TextNode, HashtagNode]};
<LexicalComposer initialConfig={initialConfig}><HashtagPlugin /></LexicalComposer> // ok Defensive patterns
Strategy: validation
Validate before calling
import {HashtagNode} from '@lexical/hashtag';
if (!editor.hasNodes([HashtagNode])) {
throw new Error('Add HashtagNode to your editor nodes config before using HashtagPlugin');
} Type guard
function supportsHashtags(editor: LexicalEditor): boolean {
return editor.hasNodes([HashtagNode]);
} Try / catch
try {
if (!editor.hasNodes([HashtagNode])) throw new Error('HashtagNode missing');
// render/use plugin
} catch (e) {
console.error('HashtagPlugin misconfigured:', e);
} Prevention
- Render plugins conditionally only after node registration is confirmed
- List all decorator/transform node classes in initialConfig.nodes
- Run editor.hasNodes checks in dev-mode editor factory
When it happens
Trigger: Rendering <HashtagPlugin /> inside a LexicalComposer whose editor was created without HashtagNode in its nodes array.
Common situations: Building a custom editor configuration by hand and forgetting @lexical/hashtag's node; adding the plugin copied from the playground to an app with a minimal nodes list; switching from a preset (e.g. rich text extension bundle) to explicit node registration.
Related errors
- LinkPlugin: LinkNode not registered on editor
- ListPlugin: ListNode and/or ListItemNode not registered on e
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- CodeHighlightPlugin: CodeNode or CodeHighlightNode not regis
- Unrecognized charset
AI-assisted analysis of facebook/lexical@76a22dcba9 (2026-08-31).
Data as JSON: /api/errors/b40e1283897ecfa4.
Report an issue: GitHub.