{"record":{"id":"7e8483c9a14fde15","repo":"hexojs/hexo","slug":"fn-must-be-a-function-7e8483","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/generator.ts","lineNumber":49,"sourceCode":"  }\n\n  list(): Store {\n    return this.store;\n  }\n\n  get(name: string): StoreFunction {\n    return this.store[name];\n  }\n\n  register(fn: GeneratorFunction): void\n  register(name: string, fn: GeneratorFunction): void\n  register(name: string | GeneratorFunction, fn?: GeneratorFunction): void {\n    if (!fn) {\n      if (typeof name === 'function') { // fn\n        fn = name;\n        name = `generator-${this.id++}`;\n      } else {\n        throw new TypeError('fn must be a function');\n      }\n    }\n\n    if (fn.length > 1) fn = Promise.promisify(fn);\n    this.store[name as string] = Promise.method(fn);\n  }\n}\n\nexport = Generator;\n","sourceCodeStart":31,"sourceCodeEnd":59,"githubUrl":"https://github.com/hexojs/hexo/blob/059cb17494d0632a053c24077f5bcb6ae92acc51/lib/extend/generator.ts#L31-L59","documentation":"Thrown by Generator.register when no function can be resolved. Hexo generators build the site's route data; the (fn) form requires the single argument to be a function, otherwise an auto-name cannot be assigned. The (name, fn) form also requires fn callable.","triggerScenarios":"Calling register('non-function-string') with no fn, or register(someObject) where the argument is not a function.","commonSituations":"A plugin registers a generator but the handler import is undefined, or an object/config was passed instead of a function.","solutions":["Pass a function as the generator (register(fn)) or as the second argument (register(name, fn)).","Verify the imported generator symbol is defined.","Ensure you did not pass an options object as the sole argument."],"exampleFix":"// before\nhexo.extend.generator.register(genConfig);\n// after\nhexo.extend.generator.register(locals => { /* return routes */ });","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== 'function') throw new Error('generator must be a function');\nhexo.extend.generator.register(fn);","typeGuard":"const isGeneratorFn = (x: unknown): x is (...a: any[]) => any => typeof x === 'function';","tryCatchPattern":null,"preventionTips":["Register generators with the single-function form unless you need a custom name.","Confirm imported generator modules export a function.","Type generator registration wrappers to reject non-functions."],"tags":["generator","validation","plugin","typescript"],"backgroundTag":null,"analyzedSha":"059cb17494d0632a053c24077f5bcb6ae92acc51","analyzedAt":"2026-08-12T20:52:05.731Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}