discordjs/discord.js · error · TypeError

${fn} is not a function

Error message

${fn} is not a function

What it means

Collection.find(predicate, thisArg?) iterates the collection and returns the first value for which the predicate is truthy. It explicitly type-checks the predicate and throws a TypeError (with the stringified argument in the message) when fn is not a function, giving a clear failure instead of an opaque 'fn is not a function' crash deeper in the loop.

Source

Thrown at packages/collection/src/collection.ts:294

	 * @example
	 * ```ts
	 * collection.find(user => user.username === 'Bob');
	 * ```
	 */
	public find<NewValue extends Value>(
		fn: (value: Value, key: Key, collection: this) => value is NewValue,
	): NewValue | undefined;
	public find(fn: (value: Value, key: Key, collection: this) => unknown): Value | undefined;
	public find<This, NewValue extends Value>(
		fn: (this: This, value: Value, key: Key, collection: this) => value is NewValue,
		thisArg: This,
	): NewValue | undefined;
	public find<This>(
		fn: (this: This, value: Value, key: Key, collection: this) => unknown,
		thisArg: This,
	): Value | undefined;
	public find(fn: (value: Value, key: Key, collection: this) => unknown, thisArg?: unknown): Value | undefined {
		if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`);
		if (thisArg !== undefined) fn = fn.bind(thisArg);
		for (const { 0: key, 1: value } of this) {
			if (fn(value, key, this)) return value;
		}

		return undefined;
	}

	/**
	 * Searches for the key of a single item where the given function returns a truthy value. This behaves like
	 * {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex | Array.findIndex()},
	 * but returns the key rather than the positional index.
	 *
	 * @param fn - The function to test with (should return a boolean)
	 * @param thisArg - Value to use as `this` when executing the function
	 * @example
	 * ```ts
	 * collection.findKey(user => user.username === 'Bob');

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Pass an actual predicate function: collection.find((value, key) => ...).
  2. Check argument order — the predicate comes first, optional thisArg second.
  3. Verify the callback variable is defined/imported and not undefined at call time.
  4. If using lodash-style shorthand, rewrite it as an explicit arrow function predicate.

Example fix

// before
collection.find({ name: 'foo' }); // lodash-style, unsupported
// after
collection.find((value) => value.name === 'foo');
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof predicate !== 'function') {
  throw new TypeError('find() expects (value, key, collection) => unknown');
}

Type guard

function isPredicate<K, V>(f: unknown): f is (value: V, key: K, collection: unknown) => unknown {
  return typeof f === 'function';
}

Try / catch

try {
  const found = collection.find(fn);
} catch (err) {
  if (err instanceof TypeError && err.message.includes('is not a function')) {
    console.error('find() first argument must be a predicate function.');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling collection.find with a non-callable first argument — e.g. passing an object, a string property name, or an undefined variable that was expected to be a predicate; or accidentally passing the predicate as the second argument (thisArg slot) leaving fn non-function.

Common situations: Mixing up argument order (collection.find(thisArg, fn)); passing a value where a predicate is required after refactoring from Array.prototype.find wrappers; undefined callback due to a typo'd import; lodash-style shorthand predicates (strings/objects) which this Collection does not support.

Related errors


AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30). Data as JSON: /api/errors/81895d33173ae134. Report an issue: GitHub.