markedjs/marked · error · Error

Token with "${token.type}" type was not found.

Error message

Token with "${token.type}" type was not found.

What it means

Thrown in the default branch of the block-token switch in _Parser.parse() when a token's type is not one of the handled block types (space, hr, heading, code, table, blockquote, list, checkbox, html, def, paragraph, text) and is not covered by a registered renderer extension (Parser.ts:50-57, 111-118). With the built-in lexer this is unreachable because it only emits those types. It happens when a custom block-level tokenizer extension produces tokens of a custom type but no matching renderer extension with the same name was registered, or when a caller manually constructs/modifies the token array passed to Parser.parse/marked.parse.

Source

Thrown at src/Parser.ts:117

          out += this.renderer.def(token);
          break;
        }
        case 'paragraph': {
          out += this.renderer.paragraph(token);
          break;
        }
        case 'text': {
          out += this.renderer.text(token);
          break;
        }

        default: {
          const errMsg = 'Token with "' + token.type + '" type was not found.';
          if (this.options.silent) {
            console.error(errMsg);
            return '' as ParserOutput;
          } else {
            throw new Error(errMsg);
          }
        }
      }
    }

    return out as ParserOutput;
  }

  /**
   * Parse Inline Tokens
   */
  parseInline(tokens: Token[], renderer: _Renderer<ParserOutput, RendererOutput> | _TextRenderer<RendererOutput> = this.renderer): ParserOutput {
    this.renderer.parser = this;
    let out = '';

    for (let i = 0; i < tokens.length; i++) {
      const anyToken = tokens[i];

View on GitHub (pinned to 9552b6bbca)

Solutions

  1. Register a renderer extension with name exactly matching the token's type (e.g. extensions:[{ name:'callout', renderer(token){...} }]).
  2. Verify the casing/whitespace of the type string the tokenizer emits vs the name the renderer uses - they must be byte-identical.
  3. If hand-building tokens, only use known block token types or also register renderers for custom types.
  4. Audit any processAllTokens hook to ensure it only injects types that have renderers.
  5. For debugging, set silent:true to log the unknown type and continue with empty output instead of throwing.

Example fix

// before — tokenizer emits 'callout' but no renderer is registered
marked.use({
  extensions: [{
    name: 'callout',
    level: 'block',
    tokenizer(src) { const m = /^:::callout\n([\s\S]*?)\n:::/.exec(src); if (!m) return; return { type:'callout', raw:m[0], text:m[1], tokens:[] }; }
  }]
});

// after — add a matching renderer extension
marked.use({
  extensions: [
    { name: 'callout', level: 'block', tokenizer(src) { /* ... */ } },
    { name: 'callout', renderer(token) { return `<div class="callout">${this.parser.parse(token.tokens)}</div>`; } }
  ]
});
Defensive patterns

Strategy: validation

Validate before calling

const knownBlockTypes = new Set(['space','hr','heading','code','table','blockquote','list','checkbox','html','def','paragraph','text']);
const renderedTypes = new Set(Object.keys(markedInstance.defaults.extensions?.renderers ?? {}));
for (const ext of myExtensions) {
  if ('tokenizer' in ext && ext.level === 'block' && !knownBlockTypes.has(ext.name) && !renderedTypes.has(ext.name)) {
    throw new Error('block extension "' + ext.name + '" has a tokenizer but no renderer');
  }
}

Type guard

function hasRendererForType(type, markedInstance) {
  return ['space','hr','heading','code','table','blockquote','list','checkbox','html','def','paragraph','text'].includes(type)
    || Boolean(markedInstance.defaults.extensions?.renderers?.[type]);
}

Try / catch

try {
  return marked.parse(md);
} catch (e) {
  if (e instanceof Error && /type was not found/.test(e.message)) {
    logger.error('Unknown token type encountered; a renderer extension is missing', e.message);
    return marked.parse(md, { extensions: null });
  }
  throw e;
}

Prevention

When it happens

Trigger: A block-level tokenizer extension emits { type:'callout', ... } but only the tokenizer was registered (no renderer with name:'callout'), or the renderer was registered under a different name; directly calling marked.Parser.parse(tokens) with a hand-built token array containing an unknown type; a processAllTokens hook injects a token of an unregistered type; name mismatch where the tokenizer emits type:'note' but the renderer extension is name:'Notice'.

Common situations: Building a custom block syntax (admonitions, callouts, diagrams) and forgetting the renderer half; case mismatch between the token type string and the extension name; modifying the token stream in a processAllTokens hook; feeding tokens produced by a different markdown engine into marked's parser.

Related errors


AI-assisted analysis of markedjs/marked@9552b6bbca (2026-08-13). Data as JSON: /api/errors/1d14a8fcd2f2773c. Report an issue: GitHub.