angular/angular-cli · error · SchematicsException
Prerequisite for application shell is to define a router-out
Error message
Prerequisite for application shell is to define a router-outlet in your root component.
What it means
The app-shell schematic requires the root (bootstrap) component's template to contain a `<router-outlet>` because the generated application shell renders routes through the router. `validateProject` checks the template with a regex and throws a SchematicsException if no router-outlet exists.
Source
Thrown at packages/schematics/angular/app-shell/index.ts:131
.map((imp) => {
const pathStringLiteral = imp.moduleSpecifier as ts.StringLiteral;
return pathStringLiteral.text;
})[0];
return join(dirname(bootstrappingFilePath), componentRelativeFilePath + '.ts');
}
// end helper functions.
function validateProject(mainPath: string): Rule {
return (host: Tree) => {
const routerOutletCheckRegex = /<router-outlet.*?>([\s\S]*?)(?:<\/router-outlet>)?/;
const componentPath = getBootstrapComponentPath(host, mainPath);
const tmpl = getComponentTemplateInfo(host, componentPath);
const template = getComponentTemplate(host, componentPath, tmpl);
if (!routerOutletCheckRegex.test(template)) {
throw new SchematicsException(
`Prerequisite for application shell is to define a router-outlet in your root component.`,
);
}
};
}
function getMetadataProperty(metadata: ts.Node, propertyName: string): ts.PropertyAssignment {
const properties = (metadata as ts.ObjectLiteralExpression).properties;
const property = properties.filter(ts.isPropertyAssignment).filter((prop) => {
const name = prop.name;
switch (name.kind) {
case ts.SyntaxKind.Identifier:
return name.getText() === propertyName;
case ts.SyntaxKind.StringLiteral:
return name.text === propertyName;
}
return false;View on GitHub (pinned to bb72145f9a)
Solutions
- Add `<router-outlet></router-outlet>` to the root component's template (found via getBootstrapComponentPath from the main entry)
- Run `ng add @angular/router` / set up routing first, then re-run the app-shell schematic
- Ensure the bootstrap component path resolves to the component you expect (check `main.ts` bootstrapModule/AppComponent)
Example fix
// before
@Component({ selector: 'app-root', template: '<h1>Hello</h1>' })
// after
@Component({ selector: 'app-root', template: '<h1>Hello</h1><router-outlet></router-outlet>' }) Defensive patterns
Strategy: validation
Validate before calling
const template = fs.readFileSync(rootComponentTemplatePath, 'utf8');
if (!/<router-outlet.*?>/.test(template)) {
throw new Error('Add <router-outlet> to the root component template before running app-shell');
} Try / catch
try {
await ngGenerate('app-shell', options);
} catch (e) {
if (e.message.includes('router-outlet')) {
console.error('Root component needs <router-outlet> in its template');
} else throw e;
} Prevention
- Set up Angular Router and add router-outlet to the root component before adding an app shell
- Run `ng add @angular/router` first in fresh projects
- Confirm the bootstrap component resolved from main.ts is the one containing the outlet
When it happens
Trigger: Running `ng add @angular/... app-shell` (or `ng generate app-shell`) on a project whose bootstrap AppComponent template has no `<router-outlet>` element (including self-closing or unclosed forms matched by the regex).
Common situations: Minimal starter apps that render plain content without routing; projects where routing was added to a child component but not the root component; templates built dynamically or split so router-outlet isn't in the root template literal.
Related errors
- Couldn't find a route declaration in ${fileToAdd}.\nUse the
- The router module method doesn't have arguments at line ${li
- Option "project" is required.
- Project is not defined in this workspace.
- Targets are not defined for this project.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/005e78a57ebaaee8.
Report an issue: GitHub.