handlebars-lang/handlebars.js · error · Exception
"${name}" not defined in ${obj}
Error message
"${name}" not defined in ${obj} What it means
In strict mode (compile with { strict: true }), the template's strict() helper throws when a referenced identifier is null/undefined or missing on its parent object, instead of rendering empty. This surfaces missing data at render time. The loc option points at the offending template location.
Source
Thrown at lib/handlebars/runtime.js:113
lines[i] = options.indent + lines[i];
}
result = lines.join('\n');
}
return result;
} else {
throw new Exception(
'The partial ' +
options.name +
' could not be compiled when running in runtime-only mode'
);
}
}
// Just add water
let container = {
strict: function (obj, name, loc) {
if (obj == null || !(name in Object(obj))) {
throw new Exception('"' + name + '" not defined in ' + obj, {
loc: loc,
});
}
return container.lookupProperty(obj, name);
},
strictLookup: function (depths, name, loc) {
const result = container.lookup(depths, name);
return result !== undefined
? result
: container.strict(undefined, name, loc);
},
lookupProperty: function (parent, propertyName) {
if (Utils.isMap(parent)) {
return parent.get(propertyName);
}
let result = parent[propertyName];
if (result == null) {View on GitHub (pinned to 13a7a67991)
Solutions
- Provide all referenced fields in the context before rendering
- Use {{#if}} or the default value syntax ({{missing}}{{else}}fallback) or compile without strict:true
- Guard with lookup helpers like {{lookup obj 'name'}} or the '?:' inline-if for optional fields
Example fix
// before (throws when user.name missing)
const t = Handlebars.compile('{{user.name}}', { strict: true });
t({});
// after
const t = Handlebars.compile('{{#if user.name}}{{user.name}}{{/if}}', { strict: true });
t({}); // renders '' instead of throwing Defensive patterns
Strategy: try-catch
Validate before calling
function hasRequiredFields(ctx, keys) {
return keys.every(k => k.split('.').reduce((o, p) => (o == null ? undefined : o[p]), ctx) != null);
}
// before render: hasRequiredFields(data, ['user.name']) Type guard
function propDefined(obj, key) {
return obj != null && key in Object(obj);
} Try / catch
try {
return template(data);
} catch (e) {
if (/" not defined in /.test(e.message)) {
// log e.loc, fix data or relax strict mode
} else throw e;
} Prevention
- Validate the data shape against the template's referenced fields before rendering
- Use strict mode in tests to catch missing data early, non-strict in production if acceptable
- Fixture-test every template with representative (and minimal) data
- Use {{#if}}/defaults in templates for optional fields
When it happens
Trigger: Rendering a strict-mode compiled template with data missing a referenced key, e.g. {{user.name}} where user is undefined or name is not a property of user.
Common situations: API responses missing fields; renamed JSON keys; tests rendering templates against fixtures that omit fields; turning strict:true on to catch typos and immediately hitting partial data.
Related errors
- Invalid stack pop
- Must pass iterator to #each
- Missing helper: "${name}"
- #if requires exactly one argument
- #unless requires exactly one argument
AI-assisted analysis of handlebars-lang/handlebars.js@13a7a67991 (2026-09-02).
Data as JSON: /api/errors/1ee6fe9cc3d68c27.
Report an issue: GitHub.