hexojs/hexo · error · TypeError
fn must be a function
Error message
fn must be a function
What it means
Thrown by Box.addProcessor when the resolved processor callback is not a function. Hexo's Box registers functions that process files matched by a pattern; the call form shifts arguments so a lone function arg becomes the processor with the default pattern. If no usable function is found, this guard rejects the registration as a programmer error.
Source
Thrown at lib/box/index.ts:100
path: this.source
}, options);
}
}
_File.prototype.box = this;
return _File;
}
addProcessor(pattern: (...args: any[]) => any): void;
addProcessor(pattern: string | RegExp | Pattern | ((str: string) => any), fn: (...args: any[]) => any): void;
addProcessor(pattern: string | RegExp | Pattern | ((str: string) => any), fn?: (...args: any[]) => any): void {
if (!fn && typeof pattern === 'function') {
fn = pattern;
pattern = defaultPattern;
}
if (typeof fn !== 'function') throw new TypeError('fn must be a function');
if (!(pattern instanceof Pattern)) pattern = new Pattern(pattern);
this.processors.push({
pattern,
process: fn
});
}
_readDir(base: string, prefix = ''): BlueBirdPromise<string[]> {
const { context: ctx } = this;
const results: string[] = [];
return readDirWalker(ctx, base, results, this.ignore, prefix)
.return(results)
.map(path => this._checkFileStatus(path))
.map(file => this._processFile(file.type, file.path).return(file.path));
}
_checkFileStatus(path: string): { type: string; path: string } {View on GitHub (pinned to 059cb17494)
Solutions
- Pass the processor as a function: box.addProcessor(/\.md$/, file => { ... }) or box.addProcessor(file => { ... }).
- Verify the imported handler symbol is defined and is a function before registering (check for undefined from a broken import).
- If using the pattern+fn form, ensure the SECOND argument is the function, not a string/object.
Example fix
// before
box.addProcessor(/\.md$/, undefined);
// after
box.addProcessor(/\.md$/, file => { /* ... */ }); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof handler !== 'function') throw new Error('handler must be a function');
box.addProcessor(/\.md$/, handler); Type guard
const isProcessorFn = (x: unknown): x is (...a: any[]) => any => typeof x === 'function';
Prevention
- Type the handler parameter explicitly so the compiler rejects non-functions.
- Log the imported symbol before registering to catch undefined imports.
- Prefer the two-argument form (pattern, fn) to avoid argument-shift ambiguity.
When it happens
Trigger: Calling box.addProcessor('/\.md$/') (pattern string with no second fn argument), box.addProcessor(undefined), or box.addProcessor(pattern, null) where the second argument is not a function.
Common situations: A plugin or theme script registers a processor but the imported handler resolved to undefined (bad import path, cyclic import), or the author passed a config object instead of a function, or forgot the callback in the two-argument form.
Related errors
- fn must be a function
- fn must be a function
- fn must be a function
- fn must be a function
- name is required
AI-assisted analysis of hexojs/hexo@059cb17494 (2026-08-12).
Data as JSON: /api/errors/1237d07fe9f37db8.
Report an issue: GitHub.