angular/angular-cli · error · SchematicsException
Can only specify one value for implements when generating a
Error message
Can only specify one value for implements when generating a functional guard.
What it means
Functional guards (`--functional`) are a single function typed by exactly one interface, so the schematic forbids multiple `implements` values in that mode. When `options.implements.length > 1 && options.functional`, this SchematicsException is thrown. Class-based guards can implement several interfaces; functional ones cannot.
Source
Thrown at packages/schematics/angular/guard/index.ts:20
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Rule, SchematicsException } from '@angular-devkit/schematics';
import { generateFromFiles } from '../utility/generate-from-files';
import { Implement as GuardInterface, Schema as GuardOptions } from './schema';
export default function (options: GuardOptions): Rule {
if (!options.implements) {
throw new SchematicsException('Option "implements" is required.');
}
if (options.implements.length > 1 && options.functional) {
throw new SchematicsException(
'Can only specify one value for implements when generating a functional guard.',
);
}
if (options.functional) {
const guardType = options.implements[0] + 'Fn';
return generateFromFiles({ ...options, templateFilesDirectory: './type-files' }, { guardType });
} else {
const implementations = options.implements
.map((implement) => (implement === 'CanDeactivate' ? 'CanDeactivate<unknown>' : implement))
.join(', ');
const commonRouterNameImports = ['ActivatedRouteSnapshot', 'RouterStateSnapshot'];
const routerNamedImports: string[] = [...options.implements, 'MaybeAsync', 'GuardResult'];
if (options.implements.includes(GuardInterface.CanMatch)) {
routerNamedImports.push('Route', 'UrlSegment');
View on GitHub (pinned to bb72145f9a)
Solutions
- Provide only one value when using `--functional`: `ng g guard auth --functional --implements CanActivate`.
- If you truly need multiple interfaces, drop `--functional` to generate a class-based guard implementing several.
- Generate multiple separate functional guards, one per interface, and compose them in your route config.
Example fix
// before ng g guard auth --functional --implements CanActivate,CanDeactivate // after ng g guard auth --functional --implements CanActivate // or class-based: ng g guard auth --implements CanActivate,CanDeactivate
Defensive patterns
Strategy: validation
Validate before calling
if (options.functional && Array.isArray(options.implements) && options.implements.length > 1) {
throw new Error('Functional guards accept exactly one --implements value.');
} Type guard
function validFunctionalOptions(o: { functional?: boolean; implements?: string[] }): boolean {
return !(o.functional && (o.implements?.length ?? 0) > 1);
} Try / catch
try {
await runSchematic('guard', options);
} catch (e) {
if (e instanceof SchematicsException && e.message.includes('only specify one value')) {
console.error('Use one --implements value with --functional, or drop --functional for multi-interface class guards.');
} else throw e;
} Prevention
- Pair `--functional` with exactly one interface name.
- Generate separate functional guards per interface instead of one guard with many.
- Update legacy scripts that pass comma-separated --implements lists together with --functional.
When it happens
Trigger: Running `ng generate guard <name> --functional --implements CanActivate,CanDeactivate` (two or more comma-separated values with the functional flag), or passing an array of multiple interface names programmatically with `functional: true`.
Common situations: Users upgrading from class-based guard generation who kept multi-value `--implements` habits; copy-pasted commands from class-guard examples; custom tooling that appends multiple interfaces unconditionally.
Related errors
- Option "implements" is required.
- Option "project" is required.
- Project is not defined in this workspace.
- Targets are not defined for this project.
- Content at path "${this.path}" has changed between the start
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/3d5837eae26f579c.
Report an issue: GitHub.