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

  1. Ensure a real, readable package.json exists at the project root directory passed to Parcel.
  2. If using a custom/virtual FS, make sure the package.json file is registered in the filesystem (written with writeFile) before Parcel runs.
  3. Check that the `projectRoot`/`rootDir` option points at a directory containing a valid package.json, not a parent or sibling.
  4. 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

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


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/0deae075cf6d925f. Report an issue: GitHub.