expressjs/express · error · Error
No default engine was specified and no extension was provide
Error message
No default engine was specified and no extension was provided.
What it means
The View constructor (lib/view.js:60-62) needs to know which template engine to use. It derives this from the file extension of the view name, falling back to the app's 'view engine' setting. If the render name has no extension and no default engine was configured, Express cannot pick an engine and throws synchronously.
Source
Thrown at lib/view.js:61
* - `defaultEngine` the default template engine name
* - `engines` template engine require() cache
* - `root` root path for view lookup
*
* @param {string} name
* @param {object} options
* @public
*/
function View(name, options) {
var opts = options || {};
this.defaultEngine = opts.defaultEngine;
this.ext = extname(name);
this.name = name;
this.root = opts.root;
if (!this.ext && !this.defaultEngine) {
throw new Error('No default engine was specified and no extension was provided.');
}
var fileName = name;
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)
View on GitHub ↗ (pinned to a3714473fe)
Solutions
- Set a default engine: app.set('view engine', 'pug') — note the space, not a hyphen.
- Or include the extension explicitly in every render call: res.render('index.pug').
- If using a mounted sub-app, set 'view engine' on the sub-app too (settings like this are consulted on the app doing the rendering).
Example fix
// before
app.set('view-engine', 'ejs'); // typo: sets an unrelated key
res.render('index');
// after
app.set('view engine', 'ejs');
res.render('index'); Defensive patterns
Strategy: validation
Validate before calling
if (!app.get('view engine') && !path.extname(viewName)) {
throw new Error(`Cannot render '${viewName}': set app.set('view engine', ...) or include the file extension`);
} Try / catch
try {
res.render('index'); // no extension
} catch (err) {
if (/No default engine was specified/.test(err.message)) {
// configure app.set('view engine', 'pug') or render 'index.pug'
}
next(err);
} Prevention
- Always call app.set('view engine', '<ext>') during app setup, before any route renders.
- Alternatively, always include the extension in render calls: res.render('index.ejs').
- Centralize view configuration in one bootstrap module so it can't be skipped in some entry points.
- Smoke-test one render in CI so missing engine config fails the build, not production.
When it happens
Trigger: res.render('index') (no extension) without ever calling app.set('view engine', 'ejs'|'pug'|...); calling app.render() on a bare name with the 'view engine' setting unset or misspelled (e.g. app.set('view-engine', 'ejs') — wrong key, a very common typo).
Common situations: Tutorial code that installed the engine package but skipped the app.set('view engine', ...) line; the 'view-engine' hyphen typo (silently sets an unused setting); rendering from a mounted sub-app that doesn't inherit the parent's setting the way the developer expected; tests constructing the app without the shared configuration bootstrap.
Related errors
- callback function required
- Failed to lookup view "' + name + '" in views ' + dirs
- Module "' + mod + '" does not provide a view engine.
- unknown value for etag function: ' + val
- unknown value for query parser function: ' + val
AI-assisted analysis of expressjs/express@a3714473fe (2026-07-31).
Data as JSON: /data/errors/d9fd5aafaca0abe4.json.
Report an issue: GitHub ↗.