emberjs/ember.js · error
You used ${variable}.${tail.join('.')} as a tag name, but ${
Error message
You used ${variable}.${tail.join('.')} as a tag name, but ${variable} is not in scope What it means
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.
Source
Thrown at packages/@glimmer/syntax/lib/v2/normalize.ts:853
? { result: ASTv2.STRICT_RESOLUTION }
: this.ctx.resolutionFor(path, ComponentSyntaxContext);
if (resolution.result === 'error') {
throw generateSyntaxError(
`You attempted to invoke a path (\`<${resolution.path}>\`) but ${resolution.head} was not in scope`,
loc
);
}
return new ExpressionNormalizer(this.ctx).normalize(path, resolution.result);
} else {
this.ctx.table.allocateFree(variable, ASTv2.STRICT_RESOLUTION);
}
// If the tag name wasn't a valid component but contained a `.`, it's
// a syntax error.
if (tail.length > 0) {
throw generateSyntaxError(
`You used ${variable}.${tail.join('.')} as a tag name, but ${variable} is not in scope`,
loc
);
}
return 'ElementHead';
}
private get expr(): ExpressionNormalizer {
return new ExpressionNormalizer(this.ctx);
}
}
class Children {
readonly namedBlocks: ASTv2.NamedBlock[];
readonly hasSemanticContent: boolean;
readonly nonBlockChildren: ASTv2.ContentNode[];
View on GitHub (pinned to 26f97246a8)
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.
Example fix
// before <cards.header @title="Hi" /> // after import CardsHeader from './cards/header'; <CardsHeader @title="Hi" />
Defensive patterns
Strategy: validation
Validate before calling
// Reject dotted tag names whose head is not a known binding.
function validateTag(tag, scope) {
const [head, ...tail] = tag.split('.');
if (tail.length && !scope.has(head)) {
throw new Error(`Tag ${tag}: '${head}' is not in scope`);
}
} Prevention
- 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.
When it happens
Trigger: 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`).
Common situations: 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.
Related errors
- You attempted to pass a path as argument (\`${arg.name}={{${
- Unexpected named block at the top-level of a template
- Unexpected named block nested in a normal block
- <:${name.chars}/> is not a valid named block: named blocks c
- Unexpected named block inside <:${name.chars}> named block:
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/82e41346166224aa.
Report an issue: GitHub.