angular/angular-cli · error · UnknownUrlSourceProtocol

Unknown Protocol on url "${url}".

Error message

Unknown Protocol on url "${url}".

What it means

Thrown by Engine#createSourceFromUrl when a Source URL scheme is not one of the protocols the schematics engine knows how to handle (e.g. 'file:', 'empty:', or a registered handler). If the host's createSourceFromUrl returns falsy, the URL protocol is unsupported. This is a fail-fast guard so the user knows their Source URL scheme cannot be resolved.

Source

Thrown at packages/angular_devkit/schematics/src/engine/engine.ts:377

  transformOptions<OptionT extends object, ResultT extends object>(
    schematic: Schematic<CollectionT, SchematicT>,
    options: OptionT,
    context?: TypedSchematicContext<CollectionT, SchematicT>,
  ): Observable<ResultT> {
    return this._host.transformOptions<OptionT, ResultT>(schematic.description, options, context);
  }

  createSourceFromUrl(url: Url, context: TypedSchematicContext<CollectionT, SchematicT>): Source {
    switch (url.protocol) {
      case 'null:':
        return () => new NullTree();
      case 'empty:':
        return () => empty();
    }

    const hostSource = this._host.createSourceFromUrl(url, context);
    if (!hostSource) {
      throw new UnknownUrlSourceProtocol(url.toString());
    }

    return hostSource;
  }

  executePostTasks(): Observable<void> {
    const executors = new Map<string, TaskExecutor>();

    const taskObservable = observableFrom(this._taskSchedulers).pipe(
      concatMap((scheduler) => scheduler.finalize()),
      concatMap((task) => {
        const { name, options } = task.configuration;

        const executor = executors.get(name);
        if (executor) {
          return executor(options, task.context);
        }

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Use a supported protocol, e.g. url('file:./templates') or the 'empty:' scheme.
  2. Register a custom protocol handler on the host so createSourceFromUrl can resolve the scheme.
  3. Log/print the URL and verify the scheme spelling and that a filesystem path is valid.

Example fix

// before
const src = url('https://example.com/templates');
// after
const src = url('file:./templates');
Defensive patterns

Strategy: validation

Validate before calling

const supported = ['file:', 'empty:'];
if (!supported.some(p => url.startsWith(p))) {
  throw new Error(`Unsupported URL protocol: ${url}`);
}

Type guard

function hasSupportedProtocol(url: URL): boolean {
  return url.protocol === 'file:' || url.protocol === 'empty:';
}

Try / catch

try {
  const src = host.createSourceFromUrl(url, context);
  if (!src) throw new Error(`No handler for protocol: ${url.protocol}`);
} catch (err) {
  console.error(`URL protocol not supported: ${url}`);
}

Prevention

When it happens

Trigger: Calling sourceUrl(url) (or a rule/source with a url) whose protocol is not 'file:' or 'empty:' and which is not registered via HostCreateOptions handler — the host lookup returns undefined.

Common situations: Typos in URL scheme (e.g. 'https://', 'http://', relative paths with no protocol); using a custom scheme without registering a protocol handler on the HostTree; copying examples from docs using schemes the version in use doesn't support.

Related errors


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