jashkenas/underscore · error · Error

bindAll must be passed function names

Error message

bindAll must be passed function names

What it means

_.bindAll binds each named method of an object to that object; the method names come from the remaining rest arguments. If, after flattening, no keys were supplied at all, there is nothing to bind, so the library throws. This is almost always a call-site mistake rather than a data problem.

Source

Thrown at modules/bindAll.js:11

import restArguments from './restArguments.js';
import flatten from './_flatten.js';
import bind from './bind.js';

// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
export default restArguments(function(obj, keys) {
  keys = flatten(keys, false, false);
  var index = keys.length;
  if (index < 1) throw new Error('bindAll must be passed function names');
  while (index--) {
    var key = keys[index];
    obj[key] = bind(obj[key], obj);
  }
  return obj;
});

View on GitHub (pinned to e70d5bd070)

Solutions

  1. Pass at least one method name: _.bindAll(obj, 'method1', 'method2') or an array _.bindAll(obj, names).
  2. Verify the variable holding the names array is non-empty at the call site (console.log(names) before the call).
  3. Fix the upstream filter/derivation that produced an empty list of names.
  4. If names can legitimately be empty, skip the call when names.length === 0 instead of invoking bindAll.
  5. Consider whether you intended to spread the array: _.bindAll(obj, ...names) instead of _.bindAll(obj, names) (both work here due to internal flatten, but an empty array in either form still throws).

Example fix

// before
_.bindAll(view, view.eventNames); // eventNames is []
// Error: bindAll must be passed function names

// after
if (view.eventNames.length > 0) {
  _.bindAll(view, view.eventNames);
}
Defensive patterns

Strategy: validation

Validate before calling

function safeBindAll(obj, names) {
  const flat = names.flat(Infinity);
  if (!Array.isArray(names) || flat.length === 0) return obj; // nothing to bind
  return _.bindAll(obj, ...flat);
}

Type guard

const hasNamesToBind = (names) =>
  Array.isArray(names) && names.flat(Infinity).length > 0;

Try / catch

try {
  return _.bindAll(obj, ...names);
} catch (e) {
  if (e instanceof Error && /bindAll must be passed function names/.test(e.message)) {
    return obj; // binding zero methods is a no-op
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling _.bindAll(obj) with no method-name arguments, or _.bindAll(obj, []) or _.bindAll(obj, [], []) — any call whose flattened rest-argument list has length 0.

Common situations: Spreading a possibly-empty array of names: _.bindAll(obj, ...names); building the method-name list dynamically from a filter that matched nothing; migrating from code where defaults filled in the names and the defaults were removed; copying an example and forgetting to replace placeholder method names.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jashkenas/underscore@e70d5bd070 (2026-08-29). Data as JSON: /api/errors/e4cfad7d6914d86c. Report an issue: GitHub.