{"record":{"id":"344d7e6b787a982b","repo":"emberjs/ember.js","slug":"unexpected-literal-value","errorCode":null,"errorMessage":"Unexpected literal `${value}`","messagePattern":"Unexpected literal `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@glimmer/syntax/lib/v2/normalize.ts","lineNumber":1073,"sourceCode":"  }\n}\n\nfunction isLiteral(node: ASTv1.Expression): node is ASTv1.Literal {\n  switch (node.type) {\n    case 'StringLiteral':\n    case 'BooleanLiteral':\n    case 'NumberLiteral':\n    case 'UndefinedLiteral':\n    case 'NullLiteral':\n      return true;\n    default:\n      return false;\n  }\n}\n\nfunction assertIllegalLiteral(node: ASTv1.Literal, loc: SourceSpan): never {\n  let value = node.type === 'StringLiteral' ? JSON.stringify(node.value) : String(node.value);\n  throw generateSyntaxError(`Unexpected literal \\`${value}\\``, loc);\n}\n\nfunction printPath(node: ASTv1.PathExpression | ASTv1.CallNode): string {\n  if (node.type !== 'PathExpression' && node.path.type === 'PathExpression') {\n    return printPath(node.path);\n  } else {\n    return new Printer({ entityEncoding: 'raw' }).print(node);\n  }\n}\n\nfunction printHead(node: ASTv1.PathExpression | ASTv1.CallNode): string {\n  if (node.type === 'PathExpression') {\n    return node.head.original;\n  } else if (node.path.type === 'PathExpression') {\n    return printHead(node.path);\n  } else {\n    return new Printer({ entityEncoding: 'raw' }).print(node);\n  }","sourceCodeStart":1055,"sourceCodeEnd":1091,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/syntax/lib/v2/normalize.ts#L1055-L1091","documentation":"assertIllegalLiteral fires when a literal (string, number, boolean, null, undefined) appears in a template position where only expressions/paths are legal — typically as a callee/argument position in subexpressions or as a path in a call. The value is JSON.stringify'd for strings so quotes show in the message.","triggerScenarios":"Using a literal where a path is required, e.g. {{'foo' bar}} or ('str')() as a helper name in a subexpression like {{#each (lookup 'key')}} misuse patterns, or passing a bare literal in a position the normalizer's literal assertion covers.","commonSituations":"Handwriting dynamic-looking syntax with quoted helper names, migrating handlebars that relied on lenient parsers, or typos where a string was left where a variable was intended.","solutions":["Replace the literal with a variable/path, or define the helper and call it by name","Quote via a helper if you need a literal string value (e.g. use a helper that returns the string)","Fix typos: remove stray quotes around what should be an identifier"],"exampleFix":"// before\n{{#each (items 'list') as |item|}}\n// after\n{{#each (get this \"list\") as |item|}}","handlingStrategy":"validation","validationCode":"// literal in callee position of a mustache/subexpression is illegal\nfunction literalCallee(src) {\n  return /{{\\s*['\"0-9(][^}]*\\s+\\w+\\s*\\(/.test(src);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only paths/identifiers may be called in templates; wrap literals in a helper if needed","ember-template-lint catches many literal-position mistakes","After upgrades, run the build early to surface normalizer errors"],"tags":["glimmer","handlebars","literal","template-syntax"],"backgroundTag":"illegal-literal-in-template","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}