{"record":{"id":"4e7d5c96dc5140d9","repo":"hexojs/hexo","slug":"fn-must-be-a-function-4e7d5c","errorCode":null,"errorMessage":"fn must be a function","messagePattern":"fn must be a function","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/extend/syntax_highlight.ts","lineNumber":43,"sourceCode":"\ninterface StoreFunction {\n  (content: string, options: HighlightOptions): string;\n  priority?: number;\n}\n\ninterface Store {\n  [key: string]: StoreFunction\n}\n\nclass SyntaxHighlight {\n  public store: Store;\n\n  constructor() {\n    this.store = {};\n  }\n\n  register(name: string, fn: StoreFunction): void {\n    if (typeof fn !== 'function') throw new TypeError('fn must be a function');\n\n    this.store[name] = fn;\n  }\n\n  query(name: string): StoreFunction {\n    return name && this.store[name];\n  }\n\n  exec(name: string, options: HighlightExecArgs): string {\n    const fn = this.store[name];\n\n    if (!fn) throw new TypeError(`syntax highlighter ${name} is not registered`);\n    const ctx = options.context;\n    const args = options.args || [];\n\n    return Reflect.apply(fn, ctx, args);\n  }\n}","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/hexojs/hexo/blob/059cb17494d0632a053c24077f5bcb6ae92acc51/lib/extend/syntax_highlight.ts#L25-L61","documentation":"Thrown by SyntaxHighlight.register when 'fn' is not a function. Hexo registers named syntax highlighter engines (e.g. 'highlight.js', 'prismjs'); the registered value must be a callable that performs highlighting.","triggerScenarios":"Calling hexo.extend.syntax_highlight.register(name, undefined), register(name, 'notafn'), or register(name, someObject) where the second argument is not a function.","commonSituations":"A highlighter plugin passes a configuration object instead of the highlight function, or the imported engine resolved to undefined.","solutions":["Pass a function as the highlighter implementation.","Verify the imported highlight engine is defined before registering.","Ensure the function signature matches StoreFunction."],"exampleFix":"// before\nhexo.extend.syntax_highlight.register('hljs', hljsConfig);\n// after\nhexo.extend.syntax_highlight.register('hljs', (args) => hljs.highlightAuto(args[0]).value);","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== 'function') throw new Error('highlighter must be a function');\nhexo.extend.syntax_highlight.register(name, fn);","typeGuard":"const isHighlightFn = (x: unknown): x is (...a: any[]) => any => typeof x === 'function';","tryCatchPattern":null,"preventionTips":["Pass the highlight function, not its config object.","Verify the imported engine exposes a callable before registering.","Type the registration wrapper to reject non-functions."],"tags":["syntax-highlight","validation","plugin","typescript"],"backgroundTag":null,"analyzedSha":"059cb17494d0632a053c24077f5bcb6ae92acc51","analyzedAt":"2026-08-12T20:52:05.731Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}