{"record":{"id":"ca924c3942296da6","repo":"emberjs/ember.js","slug":"unexpected-block-params-in-name-chars-simple","errorCode":null,"errorMessage":"Unexpected block params in <${name.chars}>: simple elements cannot have block params","messagePattern":"Unexpected block params in <(.+?)>: simple elements cannot have block params","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@glimmer/syntax/lib/v2/normalize.ts","lineNumber":974,"sourceCode":"    ) {\n      throw generateSyntaxError(\n        `named block <:${name.chars}> cannot have attributes, arguments, or modifiers`,\n        this.loc\n      );\n    }\n\n    let offsets = SpanList.range(this.nonBlockChildren, this.loc);\n\n    return this.block.builder.namedBlock(\n      name,\n      this.block.builder.block(table, this.nonBlockChildren, offsets),\n      this.loc\n    );\n  }\n\n  assertElement(name: SourceSlice, hasBlockParams: boolean): ASTv2.SimpleElement {\n    if (hasBlockParams) {\n      throw generateSyntaxError(\n        `Unexpected block params in <${name.chars}>: simple elements cannot have block params`,\n        this.loc\n      );\n    }\n\n    if (isPresentArray(this.namedBlocks)) {\n      let names = this.namedBlocks.map((b) => b.name);\n\n      if (names.length === 1) {\n        throw generateSyntaxError(\n          `Unexpected named block <:foo> inside <${name.chars}> HTML element`,\n          this.loc\n        );\n      } else {\n        let printedNames = names.map((n) => `<:${n.chars}>`).join(', ');\n        throw generateSyntaxError(\n          `Unexpected named blocks inside <${name.chars}> HTML element (${printedNames})`,\n          this.loc","sourceCodeStart":956,"sourceCodeEnd":992,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/syntax/lib/v2/normalize.ts#L956-L992","documentation":"Glimmer's template normalizer builds ASTv2 SimpleElementNode for plain HTML tags like <div>. If a tag has block params (e.g. <div as |x|>) but its name is not recognized as a component invocation, it cannot yield anything, so the compiler rejects the template rather than silently dropping the params.","triggerScenarios":"Compiling a template where an HTML element tag is written with block params, e.g. <div as |item|>...</div> — the parser sees |params| on a tag that resolves to a simple element.","commonSituations":"Typos in component names (lowercased or misspelled so angle-bracket resolution falls back to element), renaming a component so the old tag becomes an unknown element, or accidentally copying `as |x|` syntax onto a plain element.","solutions":["Remove the `as |...|` block params from the element tag","If the tag was meant to be a component, rename it to a valid component name (capitalized or namespaced, e.g. <MyThing> or <MyThing::Row>)","Check that the component exists/resolves where it is invoked"],"exampleFix":"// before\n<div as |item|>\n  <li>{{item}}</li>\n</div>\n// after\n<div>\n  {{#each items as |item|}}\n    <li>{{item}}</li>\n  {{/each}}\n</div>","handlingStrategy":"validation","validationCode":"function isBlockParamsOnElement(tag) {\n  return /^[a-z]/.test(tag) && /\\s+as\\s+\\|/.test(tag);\n}\n// lint templates before build: strip `as |...|` from any tag starting lowercase","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run ember-template-lint (no-block-params-on-... style rules) in CI","Avoid lowercase starting tags for components; always use PascalCase or namespaced names","Search templates for regex `<[a-z][^>]*as\\s+\\|` during refactors"],"tags":["glimmer","handlebars","template-syntax","compile-time"],"backgroundTag":"block-params-on-html-element","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}