{"record":{"id":"82e41346166224aa","repo":"emberjs/ember.js","slug":"you-used-variable-tail-join-as-a-tag-na","errorCode":null,"errorMessage":"You used ${variable}.${tail.join('.')} as a tag name, but ${variable} is not in scope","messagePattern":"You used (.+?)\\.(.+?) as a tag name, but (.+?) is not in scope","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@glimmer/syntax/lib/v2/normalize.ts","lineNumber":853,"sourceCode":"        ? { result: ASTv2.STRICT_RESOLUTION }\n        : this.ctx.resolutionFor(path, ComponentSyntaxContext);\n\n      if (resolution.result === 'error') {\n        throw generateSyntaxError(\n          `You attempted to invoke a path (\\`<${resolution.path}>\\`) but ${resolution.head} was not in scope`,\n          loc\n        );\n      }\n\n      return new ExpressionNormalizer(this.ctx).normalize(path, resolution.result);\n    } else {\n      this.ctx.table.allocateFree(variable, ASTv2.STRICT_RESOLUTION);\n    }\n\n    // If the tag name wasn't a valid component but contained a `.`, it's\n    // a syntax error.\n    if (tail.length > 0) {\n      throw generateSyntaxError(\n        `You used ${variable}.${tail.join('.')} as a tag name, but ${variable} is not in scope`,\n        loc\n      );\n    }\n\n    return 'ElementHead';\n  }\n\n  private get expr(): ExpressionNormalizer {\n    return new ExpressionNormalizer(this.ctx);\n  }\n}\n\nclass Children {\n  readonly namedBlocks: ASTv2.NamedBlock[];\n  readonly hasSemanticContent: boolean;\n  readonly nonBlockChildren: ASTv2.ContentNode[];\n","sourceCodeStart":835,"sourceCodeEnd":871,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/syntax/lib/v2/normalize.ts#L835-L871","documentation":"A tag name containing a dot (`<foo.bar>`) implies a component invocation scoped through `foo`. When `foo` is not in scope (and there is a non-empty tail), the compiler throws this syntax error — dotted element names are not valid HTML.","triggerScenarios":"Compiling a template with a dotted tag name like `<my.thing>` or `<nested.Component>` where the part before the first dot is not a scoped local/import (loose mode resolution failed to find `variable`).","commonSituations":"Migrating from curly/loose conventions where dotted names resolved contextually; typos in component paths; expecting a helper/namespace-style element name to work as a tag.","solutions":["Bind the head in scope: import the component or define `variable` via a block param / `let` / `@arg`.","If you wanted an HTML element, replace the dotted name with a valid lowercase element tag.","If it is a nested component, import it directly under its own name."],"exampleFix":"// before\n<cards.header @title=\"Hi\" />\n\n// after\nimport CardsHeader from './cards/header';\n<CardsHeader @title=\"Hi\" />","handlingStrategy":"validation","validationCode":"// Reject dotted tag names whose head is not a known binding.\nfunction validateTag(tag, scope) {\n  const [head, ...tail] = tag.split('.');\n  if (tail.length && !scope.has(head)) {\n    throw new Error(`Tag ${tag}: '${head}' is not in scope`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use plain lowercase tags for elements and imported names for components.","Do not rely on loose-mode contextual resolution of dotted names when migrating.","Lint templates for unresolved dotted tags."],"tags":["glimmer","template-compiler","scope","syntax-error"],"backgroundTag":"strict-mode-scope-resolution-failed","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}