balderdashy/sails · warning

Ignoring unexpected property in one of the exits of the help

Error message

Ignoring unexpected property in one of the exits of the helper definition loaded from ${helperDef._loadedFrom}.  Features like `responseType`, `viewTemplatePath`, and `statusCode` can only be used by actions, not by helpers!

What it means

Exit definitions in helpers may not use action-only properties such as `responseType`, `viewTemplatePath`, or `statusCode`. If any exit of a loaded helper defines one of these, the helpers hook logs this warning identifying the source file, and the offending property is ignored. These features control HTTP responses, which only actions produce.

Source

Thrown at lib/hooks/helpers/private/load-helpers.js:84

              'from '+helperDef._loadedFrom+'.  This feature can only be used '+
              'by actions, not by helpers!'
            );
          }
          var hasAnyConfusingExitProps = (
            _.isObject(helperDef.exits) &&
            _.any(helperDef.exits, function(exitDef){
              return (
                _.isObject(exitDef) &&
                (
                  exitDef.responseType !== undefined ||
                  exitDef.viewTemplatePath !== undefined ||
                  exitDef.statusCode !== undefined
                )
              );
            })
          );
          if (hasAnyConfusingExitProps) {
            sails.log.warn(
              'Ignoring unexpected property in one of the exits of the helper '+
              'definition loaded from '+helperDef._loadedFrom+'.  Features like '+
              '`responseType`, `viewTemplatePath`, and `statusCode` can only be '+
              'used by actions, not by helpers!'
            );
          }

          // Build & expose helper on `sails.helpers`
          // > e.g. sails.helpers.userHelpers.foo.myHelper
          sails.hooks.helpers.furnishHelper(keyPath, helperDef);
        } catch (err) {
          // If an error occurs building the callable, throw here to bust
          // out of the _.each loop early
          throw flaverr({
            code: 'E_FAILED_TO_BUILD_CALLABLE',
            identity: helperDef.identity,
            loadedFrom: identity,
            raw: err

View on GitHub (pinned to 7b76422cc2)

Solutions

  1. Remove responseType/viewTemplatePath/statusCode from the helper's exit definitions.
  2. Handle response customization in the calling action: switch on the helper's exits (exits: { badRequest: { responseType: 'badRequest' } } on the action side).
  3. Keep helper exits plain (description-only) and let actions decide how to respond.

Example fix

// before (helper exits)
exits: { notFound: { responseType: 'notFound', statusCode: 404 } }
// after (helper)
exits: { notFound: { description: 'Record not found.' } }
// ...and in the calling action: exits: { notFound: { responseType: 'notFound' } }
Defensive patterns

Strategy: validation

Validate before calling

const actionOnly = ['responseType', 'viewTemplatePath', 'statusCode'];
for (const [name, exit] of Object.entries(helperDef.exits || {})) {
  const offending = actionOnly.filter(k => exit[k] !== undefined);
  if (offending.length) console.warn(`Exit '${name}' uses action-only props: ${offending}`);
}

Prevention

When it happens

Trigger: A helper's exits dictionary includes e.g. exits.badRequest = { responseType: 'badRequest' } or { statusCode: 400 } or { viewTemplatePath: '...' }, detected by hasAnyConfusingExitProps during helper loading.

Common situations: Copy-pasting exit definitions from actions into helpers, assuming helper exits behave like action exits for response negotiation, or migrating legacy response-handling code into helpers.

Related errors


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