{"record":{"id":"66b270ff40558e9f","repo":"markedjs/marked","slug":"extension-name-required","errorCode":null,"errorMessage":"extension name required","messagePattern":"extension name required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Instance.ts","lineNumber":112,"sourceCode":"   * behavior and extensions registered by earlier calls.\n   *\n   * Use this method when supplying only some hook methods.\n   */\n  use(...args: MarkedExtension<ParserOutput, RendererOutput>[]) {\n    const extensions: MarkedOptions<ParserOutput, RendererOutput>['extensions'] = this.defaults.extensions || { renderers: {}, childTokens: {} };\n\n    args.forEach((pack) => {\n      // copy options to new object\n      const opts = { ...pack } as MarkedOptions<ParserOutput, RendererOutput>;\n\n      // set async to true if it was set to true before\n      opts.async = this.defaults.async || opts.async || false;\n\n      // ==-- Parse \"addon\" extensions --== //\n      if (pack.extensions) {\n        pack.extensions.forEach((ext) => {\n          if (!ext.name) {\n            throw new Error('extension name required');\n          }\n          if ('renderer' in ext) { // Renderer extensions\n            const prevRenderer = extensions.renderers[ext.name];\n            if (prevRenderer) {\n              // Replace extension with func to run new extension but fall back if false\n              extensions.renderers[ext.name] = function(...args) {\n                let ret = ext.renderer.apply(this, args);\n                if (ret === false) {\n                  ret = prevRenderer.apply(this, args);\n                }\n                return ret;\n              };\n            } else {\n              extensions.renderers[ext.name] = ext.renderer;\n            }\n          }\n          if ('tokenizer' in ext) { // Tokenizer Extensions\n            if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/markedjs/marked/blob/9552b6bbca7f587f96b7249c5833358a17a18e2b/src/Instance.ts#L94-L130","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmarked.use({\n  extensions: [{\n    renderer(token) { return `<x>${token.text}</x>`; }\n  }]\n});\n\n// after\nmarked.use({\n  extensions: [{\n    name: 'x',\n    renderer(token) { return `<x>${token.text}</x>`; }\n  }]\n});","handlingStrategy":"validation","validationCode":"function validateExtensions(exts) {\n  for (const ext of exts ?? []) {\n    if (!ext.name || typeof ext.name !== 'string') {\n      throw new TypeError('marked extension missing required \"name\": ' + JSON.stringify(ext));\n    }\n  }\n}\nvalidateExtensions(myExt.extensions);\nmarked.use(myExt);","typeGuard":"function isNamedExtension(ext) {\n  return typeof ext?.name === 'string' && ext.name.length > 0;\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["configuration","extensions","marked-use","validation"],"backgroundTag":null,"analyzedSha":"9552b6bbca7f587f96b7249c5833358a17a18e2b","analyzedAt":"2026-08-13T04:27:55.513Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}