parcel-bundler/parcel · error · ThrowableDiagnostic
Expected package.json file in ${rootDir}
Error message
Expected package.json file in ${rootDir} What it means
TargetRequest loads the nearest package.json via loadConfig. If a config object is returned (`conf` is truthy) but `conf.files[0]` is null/undefined, the loader could not record an actual package.json file on disk. This indicates the package.json resolution returned a virtual/injected config without a backing file, which Parcel cannot use for target parsing.
Source
Thrown at packages/core/core/src/requests/TargetRequest.js:469
let rootFileProject = toProjectPath(this.options.projectRoot, rootFile);
// Invalidate whenever a package.json file is added.
this.api.invalidateOnFileCreate({
fileName: 'package.json',
aboveFilePath: rootFileProject,
});
let pkg;
let pkgContents;
let pkgFilePath: ?FilePath;
let pkgDir: FilePath;
let pkgMap;
if (conf) {
pkg = (conf.config: PackageJSON);
let pkgFile = conf.files[0];
if (pkgFile == null) {
throw new ThrowableDiagnostic({
diagnostic: {
message: md`Expected package.json file in ${rootDir}`,
origin: '@parcel/core',
},
});
}
let _pkgFilePath = (pkgFilePath = pkgFile.filePath); // For Flow
pkgDir = path.dirname(_pkgFilePath);
pkgContents = await this.fs.readFile(_pkgFilePath, 'utf8');
pkgMap = parse(pkgContents, undefined, {tabWidth: 1});
let pp = toProjectPath(this.options.projectRoot, _pkgFilePath);
this.api.invalidateOnFileUpdate(pp);
this.api.invalidateOnFileDelete(pp);
} else {
pkg = {};
pkgDir = this.fs.cwd();
}View on GitHub (pinned to 59484858a1)
Solutions
- Ensure a real, readable package.json exists at the project root directory passed to Parcel.
- If using a custom/virtual FS, make sure the package.json file is registered in the filesystem (written with writeFile) before Parcel runs.
- Check that the `projectRoot`/`rootDir` option points at a directory containing a valid package.json, not a parent or sibling.
- Verify no config overlay plugin is replacing package.json resolution with a fileless result.
Example fix
// before — virtual FS missing the file
await parcelFS.writeFile('/proj/index', '');
// loadConfig finds contents but conf.files is []
// after — register the real file
await parcelFS.writeFile('/proj/package.json', JSON.stringify({
name: 'app', source: 'src/index.html'
})); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, statSync } from 'fs';
import path from 'path';
function assertPkgJson(rootDir) {
const p = path.join(rootDir, 'package.json');
if (!existsSync(p) || !statSync(p).isFile()) {
throw new Error(`Missing package.json at ${rootDir}`);
}
if (statSync(p).size === 0) {
throw new Error(`Empty package.json at ${p}`);
}
} Type guard
function hasBackingFile(conf) {
return conf != null && Array.isArray(conf.files) && conf.files[0] != null && typeof conf.files[0].filePath === 'string';
} Try / catch
try {
await parcel.run();
} catch (e) {
if (/Expected package\.json file in/.test(e.message)) {
console.error('No readable package.json found. Ensure the projectRoot has a real package.json.');
} else throw e;
} Prevention
- Always pass a projectRoot that contains a real, non-empty package.json.
- When using a virtual/memory FS, write the package.json file before constructing Parcel.
- Validate config-file presence in a pre-build step.
When it happens
Trigger: Calling Parcel programmatically with a custom/overlay config that yields a parsed package.json but no file path; a virtual filesystem where loadConfig resolves config contents but fails to track the source file; a corrupted or empty package.json that loadConfig parsed from a non-file source.
Common situations: Using a memory FS in tests that injects package.json contents without registering a file; a third-party config plugin that synthesizes package.json; broken symlinks pointing at package.json; running Parcel from a directory where package.json exists but is unreadable or zero-length.
Related errors
- ${path.relative(process.cwd(), source)} is not a file.
- ${path.relative(process.cwd(), source)} does not exist.
- Could not find entry: ${entry}
- Error parsing ${path.relative(this.options.inputFS.cwd(), pk
- Could not find parcel config at ${path.relative(options.proj
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/0deae075cf6d925f.
Report an issue: GitHub.