{"record":{"id":"551093d1a38946b6","repo":"emberjs/ember.js","slug":"invalid-block-parameters-syntax-block-parameters","errorCode":null,"errorMessage":"Invalid block parameters syntax: block parameters must be preceded by the `as` keyword","messagePattern":"Invalid block parameters syntax: block parameters must be preceded by the `as` keyword","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@glimmer/syntax/lib/parser/tokenizer-event-handlers.ts","lineNumber":302,"sourceCode":"\n  finishAttributeValue(): void {\n    this.finalizeTextPart();\n\n    let tag = this.currentTag;\n    let tokenizerPos = this.offset();\n\n    if (tag.type === 'EndTag') {\n      throw generateSyntaxError(\n        `Invalid end tag: closing tag must not have attributes`,\n        this.source.spanFor({ start: tag.start.toJSON(), end: tokenizerPos.toJSON() })\n      );\n    }\n\n    let { name, parts, start, isQuoted, isDynamic, valueSpan } = this.currentAttr;\n\n    // Just trying to be helpful with `<Hello |foo|>` rather than letting it through as an attribute\n    if (name.startsWith('|') && parts.length === 0 && !isQuoted && !isDynamic) {\n      throw generateSyntaxError(\n        'Invalid block parameters syntax: block parameters must be preceded by the `as` keyword',\n        start.until(start.move(name.length))\n      );\n    }\n\n    let value = this.assembleAttributeValue(parts, isQuoted, isDynamic, start.until(tokenizerPos));\n    value.loc = valueSpan.withEnd(tokenizerPos);\n\n    let attribute = b.attr({ name, value, loc: start.until(tokenizerPos) });\n\n    this.currentStartTag.attributes.push(attribute);\n  }\n\n  private parsePossibleBlockParams() {\n    // const enums that we can't use directly\n    const BEFORE_ATTRIBUTE_NAME = 'beforeAttributeName' as TokenizerState.beforeAttributeName;\n    const ATTRIBUTE_NAME = 'attributeName' as TokenizerState.attributeName;\n    const AFTER_ATTRIBUTE_NAME = 'afterAttributeName' as TokenizerState.afterAttributeName;","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/syntax/lib/parser/tokenizer-event-handlers.ts#L284-L320","documentation":"Glimmer's parser encountered an attribute-like token starting with a pipe character (e.g. `<Hello |foo|>`) that is not part of a valid block params form. Block parameters must be introduced with the `as` keyword (`<Hello as |foo|>`); a leading `|` without it is assumed to be a user mistake with block-params syntax, so the parser throws a syntax error instead of silently treating it as an attribute.","triggerScenarios":"In finishAttributeValue, when the current tag attribute name starts with '|', is unquoted, is not dynamic, and has zero parts — i.e. a template contains something like `<Component |param|>` without the preceding `as`.","commonSituations":"Typing `<Foo |bar|>` out of habit from Ruby-style blocks; copy-pasting older `<Foo |a b|>` syntax that predates the `as` requirement; forgetting `as` when converting a normal attribute into block params.","solutions":["Add the `as` keyword before the pipes: `<Hello as |foo|>`","If you intended an attribute, rename it so it does not start with `|`","Quote the value if a pipe character is genuinely part of an attribute value"],"exampleFix":"// before\n<Hello |name|>Hi {{name}}</Hello>\n// after\n<Hello as |name|>Hi {{name}}</Hello>","handlingStrategy":"validation","validationCode":"// Pre-validate template tag opening forms: any `|` after a tag name must follow `as `\nif (/<[^>\\n]*\\s\\|/.test(tagOpen) && !/<[^>\\n]*\\bas\\s\\|/.test(tagOpen)) {\n  throw new Error('Block params must use `as |name|`');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write `as |name|` with the `as` keyword before pipes","Run templates through the glimmer precompiler in CI to catch syntax errors early","Enable editor syntax highlighting/linting for handlebars/glimmer templates"],"tags":["glimmer","handlebars","template-syntax","block-params"],"backgroundTag":"invalid-block-params-syntax","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}