expressjs/express · error · Error
Module "' + mod + '" does not provide a view engine.
Error message
Module "' + mod + '" does not provide a view engine.
What it means
When no engine is registered for a view's extension, Express auto-loads one by require()-ing the extension name and reading its __express export (lib/view.js:75-85). If the module loads but exports no __express function, Express throws because it has no (path, options, callback) render entry point to call.
Source
Thrown at lib/view.js:84
if (!this.ext) {
// get extension from default engine name
this.ext = this.defaultEngine[0] !== '.'
? '.' + this.defaultEngine
: this.defaultEngine;
fileName += this.ext;
}
if (!opts.engines[this.ext]) {
// load engine
var mod = this.ext.slice(1)
debug('require "%s"', mod)
// default engine export
var fn = require(mod).__express
if (typeof fn !== 'function') {
throw new Error('Module "' + mod + '" does not provide a view engine.')
}
opts.engines[this.ext] = fn
}
// store loaded engine
this.engine = opts.engines[this.ext];
// lookup path
this.path = this.lookup(fileName);
}
/**
* Lookup view by the given `name`
*
* @param {string} name
* @private
*/View on GitHub ↗ (pinned to a3714473fe)
Solutions
- Register the engine explicitly for that extension: app.engine('html', require('ejs').renderFile).
- Use consolidate.js for engines without __express: app.engine('mustache', require('consolidate').mustache).
- If you only want to send static HTML files, skip the view system: use express.static() or res.sendFile().
- Pin/downgrade the engine to a version that still exports __express, or check its docs for the new Express integration API.
Example fix
// before
app.set('view engine', 'html'); // require('html') has no __express
// after
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html'); Defensive patterns
Strategy: validation
Validate before calling
const engine = require('pug');
if (typeof engine.__express !== 'function') {
throw new Error("Module 'pug' does not export __express; register it explicitly with app.engine()");
} Type guard
function providesViewEngine(mod) {
return mod && typeof mod.__express === 'function';
} Try / catch
try {
res.render('index');
} catch (err) {
if (/does not provide a view engine/.test(err.message)) {
// register manually: app.engine('hbs', require('hbs').__express) or the engine's documented adapter
}
next(err);
} Prevention
- Verify the template package is installed and listed in dependencies (not just present locally).
- For engines without __express (e.g. handlebars, nunjucks), register an adapter explicitly via app.engine(ext, fn).
- Match the extension in app.set('view engine', ...) to the module name Express will require.
- Exercise one render at startup so a missing/incompatible engine fails on boot.
When it happens
Trigger: Rendering a .html (or other) view whose extension maps to a package that isn't an Express-compatible engine — e.g. app.set('view engine', 'html') causes require('html'), or rendering 'page.mustache' when the mustache package (which lacks __express) is installed; any engine package that dropped or never had the __express convention.
Common situations: Setting 'view engine' to a file extension like 'html' hoping to serve static HTML (use express.static or app.engine('html', ...) instead); using mustache/swig/other engines that need consolidate.js; an engine major-version upgrade that removed __express; ESM-only engine versions whose CJS require() no longer exposes the export.
Related errors
- callback function required
- No default engine was specified and no extension was provide
- name argument is required to req.get
- name must be a string to req.get
- app.use() requires a middleware function
AI-assisted analysis of expressjs/express@a3714473fe (2026-07-31).
Data as JSON: /data/errors/f514352f90f32643.json.
Report an issue: GitHub ↗.