balderdashy/sails · warning

Ignored attempt to bind route (${path}) to unknown action ::

Error message

Ignored attempt to bind route (${path}) to unknown action :: ${target}

What it means

When a route target specifies an action by identity (e.g. `'UserController.find'` or `'user/find'`), Sails checks `sails._actions` for a loaded action with that identity. If none exists, the route binding is skipped entirely with this warning — the route is not registered and requests to it will 404.

Source

Thrown at lib/router/bind.js:145

  var self = this;

  var sails = this.sails;

  var actionIdentity;
  try {
    actionIdentity = self.getActionIdentityForTarget(target);
  } catch (e) {
    throw flaverr({name: e.name || 'sailsError', code: e.code || 'E_UNKNOWN_BIND_ERROR'}, new Error('Error attempting to bind `' + (verb || 'ALL') + ' ' + path + '` to ' + JSON.stringify(target) + ': ' + e.message));
  }

  if (_.isObject(target)) {
    // Fold any other properties in the target into a shallow clone of the "options" dictionary
    options = _.extend({}, options, _.omit(target, 'action'));
  }

  // If there's no loaded action with that identity, log a warning and continue.
  if (!sails._actions[actionIdentity]) {
    sails.log.warn('Ignored attempt to bind route (' + path + ') to unknown action ::', target);
    return;
  }

  // Add "action" property to the route options, and set the _middlewareType property if the function doesn't already have one.
  _.extend(options || {}, {action: actionIdentity, _middlewareType: (sails._actions[actionIdentity] && sails._actions[actionIdentity]._middlewareType || 'ACTION: ' + actionIdentity)});

  // Loop through all of the registered action middleware, and find
  // any that should apply to the action with the given identity.
  var actionMiddlewareToRun = _.reduce(sails._actionMiddleware, function(memo, middlewareList, key) {
    // Split the key into an array and sort it so that strings starting with '!' come first.
    var targets = key.split(',').sort();
    _.any(targets, function(target) {
      // Remove any whitespace surrounding the target.
      target = target.trim();
      // If the target starts with a '!' (meaning that any actions matching it should _not_
      // run the middleware), and the target matches, bust out of this loop early.
      if (target[0] === '!') {
        target = target.substr(1);

View on GitHub (pinned to 7b76422cc2)

Solutions

  1. Fix the action identity in the route config to match a loaded controller action exactly
  2. Verify the controller file exists in api/controllers and exports the action
  3. Check earlier lift logs for controller load failures (syntax errors, bad requires)
  4. Run `sails lift` verbosely to inspect the list of registered actions

Example fix

// before
'GET /users': 'UserController.findd'
// after
'GET /users': 'UserController.find'
Defensive patterns

Strategy: validation

Validate before calling

function assertActionExists(identity) {
  if (!sails._actions[identity]) {
    throw new Error(`Route target action '${identity}' is not registered; fix config/routes.js`);
  }
}
// call after lift, before relying on the route

Type guard

function isBoundAction(identity) {
  return typeof identity === 'string' && Boolean(sails._actions && sails._actions[identity]);
}

Prevention

When it happens

Trigger: Binding a route in config/routes.js to an action identity that was never loaded, e.g. `{'GET /foo': 'FooController.bar'}` when the controller file or action doesn't exist or failed to load.

Common situations: Typos in controller/action names, controllers in folders excluded from autoload, actions failing to load due to syntax errors earlier in lift, migrating camelCase/dashed action identities incorrectly between Sails versions.

Related errors


AI-assisted analysis of balderdashy/sails@7b76422cc2 (2026-09-01). Data as JSON: /api/errors/da8a8bb375437883. Report an issue: GitHub.