markedjs/marked · error · Error
extension name required
Error message
extension name required
What it means
Thrown by Marked.use() (and the Marked constructor, which calls use) when an entry in the extensions array has no name property. Every extension must declare a non-empty name string that identifies the token type it produces and/or renders (MarkedOptions.ts:16-22, 30-33). The name doubles as the key under which a renderer is stored and the token type the parser dispatches on, so a missing or empty name makes registration ambiguous and is rejected before any markdown is parsed. This is a synchronous, configuration-time error.
Source
Thrown at src/Instance.ts:112
* behavior and extensions registered by earlier calls.
*
* Use this method when supplying only some hook methods.
*/
use(...args: MarkedExtension<ParserOutput, RendererOutput>[]) {
const extensions: MarkedOptions<ParserOutput, RendererOutput>['extensions'] = this.defaults.extensions || { renderers: {}, childTokens: {} };
args.forEach((pack) => {
// copy options to new object
const opts = { ...pack } as MarkedOptions<ParserOutput, RendererOutput>;
// set async to true if it was set to true before
opts.async = this.defaults.async || opts.async || false;
// ==-- Parse "addon" extensions --== //
if (pack.extensions) {
pack.extensions.forEach((ext) => {
if (!ext.name) {
throw new Error('extension name required');
}
if ('renderer' in ext) { // Renderer extensions
const prevRenderer = extensions.renderers[ext.name];
if (prevRenderer) {
// Replace extension with func to run new extension but fall back if false
extensions.renderers[ext.name] = function(...args) {
let ret = ext.renderer.apply(this, args);
if (ret === false) {
ret = prevRenderer.apply(this, args);
}
return ret;
};
} else {
extensions.renderers[ext.name] = ext.renderer;
}
}
if ('tokenizer' in ext) { // Tokenizer Extensions
if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {View on GitHub (pinned to 9552b6bbca)
Solutions
- Add a non-empty name string to every object in the extensions array; the name must match the token type your tokenizer emits and/or your renderer handles.
- If you build extensions programmatically, assert each one has a string name before passing the array to use().
- Confirm the name is unique among your extensions so a later use() call does not silently chain over it.
Example fix
// before
marked.use({
extensions: [{
renderer(token) { return `<x>${token.text}</x>`; }
}]
});
// after
marked.use({
extensions: [{
name: 'x',
renderer(token) { return `<x>${token.text}</x>`; }
}]
}); Defensive patterns
Strategy: validation
Validate before calling
function validateExtensions(exts) {
for (const ext of exts ?? []) {
if (!ext.name || typeof ext.name !== 'string') {
throw new TypeError('marked extension missing required "name": ' + JSON.stringify(ext));
}
}
}
validateExtensions(myExt.extensions);
marked.use(myExt); Type guard
function isNamedExtension(ext) {
return typeof ext?.name === 'string' && ext.name.length > 0;
} Prevention
- Always define name as the first property of every extension object literal.
- Annotate the extension constant with the MarkedExtension/TokenizerExtension/RendererExtension type so TypeScript flags a missing name.
- Unit-test extension registration in isolation before parsing real markdown.
When it happens
Trigger: marked.use({ extensions: [{ renderer(token){...} }] }) where the renderer extension has no name; new Marked({ extensions: [{ level:'block', tokenizer(src){...} }] }) where the tokenizer extension has no name; programmatically building the extensions array and pushing an object whose name resolved to undefined; spreading a base extension object but omitting name.
Common situations: Adapting a marked docs example and deleting the name line thinking it was cosmetic; conditionally assembling an extension and forgetting the name branch; migrating from an older marked API where names were optional; refactoring a shared extension constant and removing the name key.
Related errors
- extension level must be 'block' or 'inline'
- renderer '${prop}' does not exist
- tokenizer '${prop}' does not exist
- hook '${prop}' does not exist
- Infinite loop on byte: ${byte}
AI-assisted analysis of markedjs/marked@9552b6bbca (2026-08-13).
Data as JSON: /api/errors/66b270ff40558e9f.
Report an issue: GitHub.