discordjs/discord.js · error · DiscordjsTypeError
InvalidType
InvalidType
Error message
Supplied ${name} is not a${an ? 'n' : ''} ${expected}. What it means
Generic typed-argument validation from DiscordjsTypeError: a constructor option or argument was passed with the wrong JavaScript type. In Collector's constructor the specific throw is options.filter not being a function, but the same code template is used across the library for any `is not a <expected>` mismatch.
Source
Thrown at packages/discord.js/src/structures/interfaces/Collector.js:101
/**
* Timeout for cleanup due to inactivity
*
* @type {?Timeout}
* @private
*/
this._idletimeout = null;
/**
* The reason the collector ended
*
* @type {?string}
* @private
*/
this._endReason = null;
if (typeof this.filter !== 'function') {
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options.filter', 'function');
}
this.handleCollect = this.handleCollect.bind(this);
this.handleDispose = this.handleDispose.bind(this);
if (options.time) this._timeout = setTimeout(() => this.stop('time'), options.time).unref();
if (options.idle) this._idletimeout = setTimeout(() => this.stop('idle'), options.idle).unref();
/**
* The timestamp at which this collector last collected an item
*
* @type {?number}
*/
this.lastCollectedTimestamp = null;
}
/**
* The Date at which this collector last collected an itemView on GitHub (pinned to a81ed8a306)
Solutions
- Pass a function to options.filter, e.g. filter: (msg) => msg.author.id === userId.
- If your condition data is an object, wrap it: filter: makePredicate(myConfig) instead of filter: myConfig.
- Check property spelling and that no earlier assignment replaced filter with a non-function.
- In TypeScript, rely on CollectorOptions typing; remove `any` casts so the compiler flags non-function filters.
Example fix
// before
const collector = channel.createMessageCollector({ filter: { author: userId } });
// after
const collector = channel.createMessageCollector({ filter: (msg) => msg.author.id === userId }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof options?.filter !== 'function') {
throw new TypeError('options.filter must be a function');
} Type guard
function hasValidFilter(options) {
return typeof options?.filter === 'function';
} Try / catch
let collector;
try {
collector = channel.createMessageCollector({ filter: (m) => m.author.id === userId });
} catch (err) {
if (err?.name === 'TypeError' && /InvalidType/.test(err.message)) {
console.error('filter must be a function');
} else throw err;
} Prevention
- Always pass filter as an arrow function, never raw config objects.
- Use TypeScript CollectorOptions typing and avoid `any` casts.
- Spell filter (singular) exactly as the API expects.
- Unit-test collector setup paths to fail fast on bad options.
When it happens
Trigger: Calling createMessageCollector / createInteractionCollector / new Collector(...) with options.filter undefined, a truthy non-function (e.g. an object like { member: ... } passed where a predicate is expected), a misspelled property (filters instead of filter), or a filter accidentally overwritten by a boolean/string.
Common situations: Refactoring a filter into a config object and forgetting to wrap it in a function; copying code where `filter:` got minified/renamed; passing await results (a collection) instead of a predicate; TypeScript users bypassing types with `as any`.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- ${defaultValueGenerator} is not a function
- ${fn} is not a function
- Reduce of empty collection with no initial value
- ShardingShardMiscalculation
- CommandInteractionOptionInvalidChannelType
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/f68fc1864bafcd1a.
Report an issue: GitHub.