tree-sitter/tree-sitter · error · Error
Grammar's 'name' property must be a string.
Error message
Grammar's 'name' property must be a string.
What it means
Thrown by `grammar({...})` when the `name` option is not a string. The grammar name drives the generated language name and parser symbols (`tree_sitter_<name>`, `TS_PARSER_NAME`), so it is mandatory and must be a string. Omitting `name` entirely (undefined), passing null, or computing it from a non-string source all fail here — this fires before the identifier-format check on the next lines.
Source
Thrown at crates/generate/src/dsl.js:303
const ruleMap = {};
for (const key of Object.keys(options.rules)) {
ruleMap[key] = true;
}
for (const key of Object.keys(baseGrammar.rules)) {
ruleMap[key] = true;
}
for (const external of externals) {
if (typeof external.name === 'string') {
ruleMap[external.name] = true;
}
}
const ruleBuilder = RuleBuilder(ruleMap);
const name = options.name;
if (typeof name !== "string") {
throw new Error("Grammar's 'name' property must be a string.");
}
if (!/^[a-zA-Z_]\w*$/.test(name)) {
throw new Error("Grammar's 'name' property must not start with a digit and cannot contain non-word characters.");
}
if (inherits && typeof inherits !== "string") {
throw new Error("Base grammar's 'name' property must be a string.");
}
if (inherits && !/^[a-zA-Z_]\w*$/.test(name)) {
throw new Error("Base grammar's 'name' property must not start with a digit and cannot contain non-word characters.");
}
const rules = Object.assign({}, baseGrammar.rules);
if (options.rules) {
if (typeof options.rules !== "object") {
throw new Error("Grammar's 'rules' property must be an object.");View on GitHub (pinned to dff1fd868c)
Solutions
- Add a string name, snake_cased: `name: 'my_language'`.
- Keep it consistent with the package name: package `tree-sitter-my-language` uses `name: 'my_language'`.
- If the name is computed, fall back to a literal default rather than shipping undefined.
Example fix
// before
module.exports = grammar({
rules: { source_file: $ => $.expr }
});
// after
module.exports = grammar({
name: 'my_language',
rules: { source_file: $ => $.expr }
}); Defensive patterns
Strategy: validation
Validate before calling
function validateGrammarOptions(options) {
if (typeof options.name !== 'string') {
throw new Error("Grammar's 'name' must be a snake_case string, e.g. 'my_language'");
}
} Type guard
const hasValidName = (o) => typeof o.name === 'string';
Prevention
- Treat `name` as required scaffolding, like package.json's name field.
- Derive it once from the package name and reuse: `name: 'my_language'` for `tree-sitter-my-language`.
- Add a smoke test that loads grammar.js and asserts `typeof grammarObj.name === 'string'`.
When it happens
Trigger: `grammar({ rules: {...} })` with no `name` key at all; `name: null`; `name: 123`; a name imported from a module that exported undefined (typo'd import name that didn't fail at load); inheriting grammars where the author assumed the base grammar's name carries over.
Common situations: Scaffolding a new grammar from a template and deleting or renaming the name field; grammars that compute `name` from package metadata with a failed lookup; inheriting grammars forgetting that the derived grammar still needs its own `name`.
Related errors
- Grammar's 'name' property must not start with a digit and ca
- Base grammar's 'name' property must be a string.
- Grammar's 'externals' property must be a function.
- Grammar's 'externals' property must return an array of rules
- Base grammar's 'name' property must not start with a digit a
AI-assisted analysis of tree-sitter/tree-sitter@dff1fd868c (2026-08-16).
Data as JSON: /api/errors/fe2f4607679e90f3.
Report an issue: GitHub.