discordjs/discord.js · error · TypeError
${defaultValueGenerator} is not a function
Error message
${defaultValueGenerator} is not a function What it means
Collection.ensure(key, defaultValueGenerator) only calls the generator if the key is absent. To keep the contract that the second argument is a factory function, it throws a TypeError when the argument is not callable, stringifying the offending value into the message.
Source
Thrown at packages/collection/src/collection.ts:55
*
* @typeParam Key - The key type this collection holds
* @typeParam Value - The value type this collection holds
*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export class Collection<Key, Value> extends Map<Key, Value> {
/**
* Obtains the value of the given key if it exists, otherwise sets and returns the value provided by the default value generator.
*
* @param key - The key to get if it exists, or set otherwise
* @param defaultValueGenerator - A function that generates the default value
* @example
* ```ts
* collection.ensure(guildId, () => defaultGuildConfig);
* ```
*/
public ensure(key: Key, defaultValueGenerator: (key: Key, collection: this) => Value): Value {
if (this.has(key)) return this.get(key)!;
if (typeof defaultValueGenerator !== 'function') throw new TypeError(`${defaultValueGenerator} is not a function`);
const defaultValue = defaultValueGenerator(key, this);
this.set(key, defaultValue);
return defaultValue;
}
/**
* Checks if all of the elements exist in the collection.
*
* @param keys - The keys of the elements to check for
* @returns `true` if all of the elements exist, `false` if at least one does not exist.
*/
public hasAll(...keys: Key[]) {
return keys.every((key) => super.has(key));
}
/**
* Checks if any of the elements exist in the collection.
*View on GitHub (pinned to a81ed8a306)
Solutions
- Wrap the default in a function: collection.ensure(key, () => defaultValue).
- If you just want a stored value, use has/get/set instead of ensure.
- Check the JSDoc example in collection.ts: `collection.ensure(guildId, () => defaultGuildConfig)`.
Example fix
// before collection.ensure(guildId, defaultGuildConfig); // after collection.ensure(guildId, () => defaultGuildConfig);
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof defaultValueGenerator !== 'function') {
throw new TypeError('ensure() requires a factory function');
} Type guard
function isFactory<V, K>(f: unknown): f is (key: K, collection: unknown) => V {
return typeof f === 'function';
} Try / catch
try {
collection.ensure(key, def as any);
} catch (err) {
if (err instanceof TypeError && err.message.includes('is not a function')) {
collection.set(key, def);
} else throw err;
} Prevention
- Always pass an arrow function: ensure(key, () => value).
- Remember ensure takes a factory, not a value.
- Add a lint rule or review note for Collection.ensure usage.
When it happens
Trigger: Calling collection.ensure(key, value) passing a non-function as the second argument — e.g. ensure('cfg', defaultConfig) instead of ensure('cfg', () => defaultConfig).
Common situations: Misreading the API as an upsert-with-value method; refactoring from get-or-set code that used plain values; copying ensure() usage from Map patterns where a default value (not factory) is expected.
Related errors
- ${fn} is not a function
- Reduce of empty collection with no initial value
- InvalidType
- Unable to resolve body.
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/817e712ae97e2b7c.
Report an issue: GitHub.