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

  1. Provide only one value when using `--functional`: `ng g guard auth --functional --implements CanActivate`.
  2. If you truly need multiple interfaces, drop `--functional` to generate a class-based guard implementing several.
  3. 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

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


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/3d5837eae26f579c. Report an issue: GitHub.