balderdashy/sails · error

E_VIEW_INFER

E_VIEW_INFER

Error message

Internal Server Error

What it means

E_VIEW_INFER is thrown by Sails' res.view() when no view path is given as an argument and none can be inferred from the request context. res.view() normally derives the view path from the current route's target (controller/action), so this error means the route was bound without enough context to guess a view. Sails then forwards the error to res.serverError() (or an optional callback), producing a 500 response with message 'Internal Server Error'.

Source

Thrown at lib/hooks/views/res.view.js:153

    // if (_.isFunction(locals)) {
    //   optionalCb = locals;
    //   locals = {};
    // }
    // if (_.isFunction(specifiedPath)) {
    //   optionalCb = specifiedPath;
    // }

    // If a view path cannot be inferred, send back an error instead
    if (!relPathToView) {
      var err = new Error();
      err.name = 'Error in res.view()';
      err.code = 'E_VIEW_INFER';
      err.type = err.code;// <<TODO remove this
      err.message = 'No path specified, and no path could be inferred from the request context.';

      // Prevent endless recursion:
      if (req._errorInResView) { return res.sendStatus(500); }
      req._errorInResView = err;

      if (optionalCb) { return optionalCb(err); }
      else {return res.serverError(err);}
    }


    // Ensure specifiedPath is a string (important)
    relPathToView = '' + relPathToView + '';

    // Ensure `locals` is an object
    locals = _.isObject(locals) ? locals : {};

    // Mixin locals from req.options.
    // TODO -- replace this _.merge() with a call to the merge-dictionaries module?
    if (req.options.locals) {
      locals = _.merge(locals, req.options.locals);
    }

View on GitHub (pinned to 7b76422cc2)

Solutions

  1. Pass the view path explicitly: res.view('pages/mypage') instead of res.view().
  2. Ensure the route target is a controller action (Controller.action string) so res.view() can infer the matching view file.
  3. Create the view file at the path Sails infers (api/views/<controller>/<action>.ejs).
  4. If the response should be JSON only, use res.json() instead of res.view().

Example fix

// before
'GET /': function (req, res) {
  res.view(); // E_VIEW_INFER: no path to infer
}
// after
'GET /': function (req, res) {
  return res.view('pages/home');
}
Defensive patterns

Strategy: validation

Validate before calling

if (typeof viewPath === 'undefined') { /* route target can't infer a view */ return res.json({ error: 'no view' }); }
return res.view(viewPath);

Type guard

function hasViewPath(req) { return typeof req.options !== 'undefined' && typeof req.options.view === 'string'; }

Try / catch

try { return res.view(pathOrUndefined); } catch (e) { if (e && e.code === 'E_VIEW_INFER') { return res.json({ error: 'view path required' }); } throw e; }

Prevention

When it happens

Trigger: Calling res.view() with no arguments inside code reached via a route that has no implicit view target, e.g. a custom standalone response handler, a policy-driven flow, or a route like 'GET /': function(req,res){ res.view(); } where no matching views/<controller>/<action>.ejs path can be guessed.

Common situations: Renaming a controller or action so the inferred view path no longer matches; calling res.view() from a route bound to an inline function instead of a Controller.action string; calling res.view() inside custom hooks, blueprints overrides, or shadow routes where no route target exists.

Understand the failure class

Related errors


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