{"record":{"id":"c78eb62e3c442371","repo":"hexojs/hexo","slug":"output-is-required","errorCode":null,"errorMessage":"output is required","messagePattern":"output is required","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/extend/renderer.ts","lineNumber":102,"sourceCode":"    return Boolean(this.get(path));\n  }\n\n  isRenderableSync(path: string): boolean {\n    return Boolean(this.get(path, true));\n  }\n\n  getOutput(path: string): string {\n    const renderer = this.get(path);\n    return renderer ? renderer.output : '';\n  }\n\n  register(name: string, output: string, fn: StoreFunctionWithCallback): void;\n  register(name: string, output: string, fn: StoreFunctionWithCallback, sync: false): void;\n  register(name: string, output: string, fn: StoreSyncFunction, sync: true): void;\n  register(name: string, output: string, fn: StoreFunctionWithCallback | StoreSyncFunction, sync: boolean): void;\n  register(name: string, output: string, fn: StoreFunctionWithCallback | StoreSyncFunction, sync?: boolean) {\n    if (!name) throw new TypeError('name is required');\n    if (!output) throw new TypeError('output is required');\n    if (typeof fn !== 'function') throw new TypeError('fn must be a function');\n\n    name = getExtname(name);\n    output = getExtname(output);\n\n    if (sync) {\n      this.storeSync[name] = fn;\n      this.storeSync[name].output = output;\n\n      this.store[name] = Promise.method(fn);\n      this.store[name].disableNunjucks = (fn as StoreFunction).disableNunjucks;\n    } else {\n      if (fn.length > 2) fn = Promise.promisify(fn);\n      this.store[name] = fn;\n    }\n\n    this.store[name].output = output;\n    this.store[name].compile = fn.compile;","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/hexojs/hexo/blob/059cb17494d0632a053c24077f5bcb6ae92acc51/lib/extend/renderer.ts#L84-L120","documentation":"Thrown by Renderer.register when the 'output' argument is falsy. The output is the target extension the renderer produces; without it Hexo cannot determine the rendered file's type.","triggerScenarios":"Calling hexo.extend.renderer.register('md', '', fn) or register('md', undefined, fn).","commonSituations":"A plugin author passes the input extension but forgets the output extension, or reads output from a missing config field.","solutions":["Pass a non-empty output extension (e.g. 'html', 'css').","Confirm the (name, output, fn) argument order is correct.","Validate the output source before registering."],"exampleFix":"// before\nhexo.extend.renderer.register('styl', out, fn);\n// after\nhexo.extend.renderer.register('styl', 'css', fn);","handlingStrategy":"validation","validationCode":"if (!output) throw new Error('renderer output required');\nhexo.extend.renderer.register(name, output, fn);","typeGuard":"const isValidOutput = (o: unknown): o is string => typeof o === 'string' && o.length > 0;","tryCatchPattern":null,"preventionTips":["Always supply the output extension in the (name, output, fn) order.","Document the expected output extension per renderer plugin.","Add a registration test asserting getOutput returns the expected value."],"tags":["renderer","validation","plugin"],"backgroundTag":null,"analyzedSha":"059cb17494d0632a053c24077f5bcb6ae92acc51","analyzedAt":"2026-08-12T20:52:05.731Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}