angular/angular-cli · error · Error
Could not parse directory path from specifier: ${specifier}
Error message
Could not parse directory path from specifier: ${specifier} What it means
In getManifest(), when npa resolves the specifier to type 'directory', the resolved `fetchSpec` is the directory path; the manifest is read from `<dir>/package.json`. If `fetchSpec` is falsy — meaning npa classified it as a directory but could not extract the actual path — this Error is thrown. It signals a malformed directory-style specifier.
Source
Thrown at packages/angular/cli/src/package-managers/package-manager.ts:599
}
versionSpec = metadata['dist-tags'][versionSpec];
} else if (type === 'range') {
const metadata = await this.getRegistryMetadata(name, options);
if (!metadata) {
return null;
}
versionSpec = maxSatisfying(metadata.versions, fetchSpec) ?? '';
}
if (!versionSpec) {
return null;
}
}
return this.getRegistryManifest(name, versionSpec, options);
}
case 'directory': {
if (!fetchSpec) {
throw new Error(`Could not parse directory path from specifier: ${specifier}`);
}
const manifestPath = join(fetchSpec, 'package.json');
const manifest = await this.host.readFile(manifestPath);
return JSON.parse(manifest);
}
case 'file':
case 'remote':
case 'git': {
if (!fetchSpec) {
throw new Error(`Could not parse location from specifier: ${specifier}`);
}
// Caching is not supported for non-registry specifiers.
const { workingDirectory, cleanup } = await this.acquireTempPackage(fetchSpec, {
...options,
ignoreScripts: true,View on GitHub (pinned to bb72145f9a)
Solutions
- Pass a complete directory specifier with a non-empty path, e.g. 'file:./packages/my-lib' instead of 'file:' or 'file:./'.
- Resolve the path to an absolute directory with path.resolve() before constructing the specifier.
- Verify the referenced directory exists and contains a package.json before calling manifest().
- If building specifiers from config variables, validate the path segment is non-empty and a real directory first.
Example fix
// before
await pm.getManifest('file:');
// after
import { resolve, existsSync } from 'node:fs';
const dir = resolve('packages/my-lib');
if (!existsSync(resolve(dir, 'package.json'))) {
throw new Error(`No package.json in directory: ${dir}`);
}
await pm.getManifest(`file:${dir}`); Defensive patterns
Strategy: validation
Validate before calling
import npa from 'npm-package-arg';
import { existsSync, statSync } from 'node:fs';
import { resolve } from 'node:path';
function assertDirectorySpec(specifier: string): string {
const parsed = npa(specifier);
if (parsed.type === 'directory') {
if (!parsed.fetchSpec) {
throw new Error(`Directory specifier missing a path: "${specifier}"`);
}
const dir = resolve(parsed.fetchSpec);
if (!existsSync(dir) || !statSync(dir).isDirectory() || !existsSync(resolve(dir, 'package.json'))) {
throw new Error(`Directory has no package.json: ${dir}`);
}
return dir;
}
return specifier;
}
// call before pm.getManifest(specifier): assertDirectorySpec(specifier); Type guard
function hasDirectoryPath(parsed: npa.Result): parsed is npa.Result & { fetchSpec: string } {
return parsed.type === 'directory' && typeof parsed.fetchSpec === 'string' && parsed.fetchSpec.length > 0;
} Try / catch
try {
const manifest = await pm.getManifest(specifier);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Could not parse directory path from specifier')) {
console.error(`Provide a non-empty directory path, e.g. file:./packages/lib: ${e.message}`);
} else {
throw e;
}
} Prevention
- Always pass a non-empty path in directory specifiers: 'file:./path/to/pkg', never 'file:' alone.
- Resolve relative paths to absolute with path.resolve() before building the specifier.
- Check the target directory contains a package.json before calling getManifest().
- Validate config/workspace variables that feed into directory specifiers are non-empty strings.
- Prefer npa() pre-parsing to confirm type === 'directory' and fetchSpec is set.
When it happens
Trigger: Calling manifest(specifier) with a directory specifier such as 'file:./', 'file:', or a npa.Result of type 'directory' whose fetchSpec resolved to an empty string, so no directory path is available to read package.json from.
Common situations: Passing 'file:' with an empty path from templated config; referencing a directory specifier whose path portion was stripped by over-trimming; programmatic specifier assembly where the path variable was empty or undefined; workspace globs resolved to empty strings.
Related errors
- Could not parse package name from specifier: ${specifier}
- Could not find ${level} workspace.
- Invalid config found at ${workspace.filePath}. CLI should be
- Could not find a ${level} workspace. Are you in a project?
- Could not find the '${builderConf}' builder's node package.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/1c87b36ab23c0767.
Report an issue: GitHub.