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
- Use a supported protocol, e.g. url('file:./templates') or the 'empty:' scheme.
- Register a custom protocol handler on the host so createSourceFromUrl can resolve the scheme.
- 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
- Only use documented protocols ('file:', 'empty:') or register custom handlers.
- Centralize URL construction in a helper that validates the scheme.
- Add a unit test that calls every source URL used in your collection.
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
- Option "project" is required.
- Project is not defined in this workspace.
- Targets are not defined for this project.
- Circular collection reference "${name}".
- Unregistered task "${name}"${addendum}.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/4f775e948ab59fb6.
Report an issue: GitHub.