emberjs/ember.js · error · Error
Attempted to resolve `${value}`, which was expected to be a
Error message
Attempted to resolve `${value}`, which was expected to be a component, but nothing was found. What it means
In a DEBUG build with a resolver, createCurryRef attempts resolver.lookupComponent for a string-based curried component definition. If the resolver returns nothing, it throws this error: the named component does not exist under the given owner/resolver.
Source
Thrown at packages/@glimmer/runtime/lib/references/curry-value.ts:56
} else if (type === CURRIED_COMPONENT && typeof value === 'string' && value) {
// Only components should enter this path, as helpers and modifiers do not
// support string based resolution
if (DEBUG) {
if (isStrict) {
throw new Error(
`Attempted to resolve a dynamic component with a string definition, \`${value}\` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly.`
);
}
let resolvedDefinition =
expect(
resolver,
'BUG: expected resolver for curried component definitions'
).lookupComponent?.(value, owner) ?? null;
if (!resolvedDefinition) {
throw new Error(
`Attempted to resolve \`${value}\`, which was expected to be a component, but nothing was found.`
);
}
}
curriedDefinition = curry(type, value, owner, args);
} else if (isIndexable(value)) {
curriedDefinition = curry(type, value, owner, args);
} else {
curriedDefinition = null;
}
lastValue = value;
return curriedDefinition;
});
}
View on GitHub (pinned to 26f97246a8)
Solutions
- Verify the component exists at the expected path (e.g. app/components/foo-bar.js|gjs|hbs) and the string matches its dasherized name exactly.
- Import the component directly and pass the definition instead of a string.
- Log/print the computed name at runtime to catch dynamically built names with typos.
- Confirm the owner/app instance the resolver uses actually contains the component (addon mounted correctly).
Example fix
// before
this.kind = 'catridge-card'; // typo
<Card @body={{component this.kind}} />
// after
this.kind = 'cartridge-card';
// or better, in strict mode:
import CartridgeCard from './cartridge-card';
<Card @body={{CartridgeCard}} /> Defensive patterns
Strategy: validation
Validate before calling
function assertComponentResolves(resolver, name, owner) {
const def = resolver.lookupComponent?.(name, owner);
if (!def) throw new Error(`Component '${name}' not found — check spelling/registration`);
return def;
} Prevention
- Keep dynamic component names in one constant list you can lint against the components directory.
- Prefer direct imports over string names even in loose mode.
- Re-check names after moving/renaming components (search for old dasherized names).
- Test dynamic rendering paths so unresolved names fail in CI, not production.
When it happens
Trigger: Passing a string component name to `{{component ...}}` in a resolver-based (loose-mode) template where no component with that name/dasherized path is registered, e.g. a typo like `{{component "foo-barr"}}` or the component lives in a different namespace the resolver can't see.
Common situations: Component renamed or moved so the resolver lookup misses; dynamically computed names with typos; pod/module structure changes (e.g. after Embroider migration) breaking resolution.
Related errors
- Attempted to resolve a dynamic component with a string defin
- Compile Error: ${template.problem} @ ${template.span.start}.
- A resolved helper cannot be passed as a named argument as th
- deprecation override for ${id} not found
- You must pass both the owner and args to super() in your com
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/7eff6e3a859effa4.
Report an issue: GitHub.