parcel-bundler/parcel · error · ThrowableDiagnostic

${path.relative(process.cwd(), source)} is not a file.

Error message

${path.relative(process.cwd(), source)} is not a file.

What it means

Thrown by assertFile() when fs.stat(source) succeeds but stat.isFile() returns false — the path exists but is a directory (or a socket/device). Parcel shows a code frame in package.json at the source value so the developer knows which field points at a non-file.

Source

Thrown at packages/core/core/src/requests/EntryRequest.js:133

            filePath: pkgFilePath,
            codeHighlights: generateJSONCodeHighlights(contents, [
              {
                key: keyPath,
                type: 'value',
              },
            ]),
          },
        ],
        hints: alternatives.map(r => {
          return md`Did you mean '__${r}__'?`;
        }),
      },
    });
  }

  if (!stat.isFile()) {
    let contents = await fs.readFile(pkgFilePath, 'utf8');
    throw new ThrowableDiagnostic({
      diagnostic: {
        origin: '@parcel/core',
        message: md`${path.relative(process.cwd(), source)} is not a file.`,
        codeFrames: [
          {
            filePath: pkgFilePath,
            codeHighlights: generateJSONCodeHighlights(contents, [
              {
                key: keyPath,
                type: 'value',
              },
            ]),
          },
        ],
      },
    });
  }
}

View on GitHub (pinned to 59484858a1)

Solutions

  1. Change the source path to point at the specific file, not the containing directory.
  2. If you intended a directory entry, add a package.json with a source field inside that directory instead.
  3. Verify with ls -la that the path is a regular file, not a directory.
  4. Check for accidental file-vs-directory name collisions (e.g., a folder named index.html).

Example fix

// before — package.json
{
  "source": "src"
}

// after
{
  "source": "src/index.html"
}
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const path = require('path');
function validateSourceIsFile(pkgPath) {
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
  const source = Array.isArray(pkg.source) ? pkg.source[0] : pkg.source;
  if (!source) return;
  const full = path.join(path.dirname(pkgPath), source);
  const stat = fs.statSync(full);
  if (!stat.isFile()) {
    throw new Error(`Source "${source}" is a ${stat.isDirectory() ? 'directory' : 'non-file'}, expected a file.`);
  }
}

Prevention

When it happens

Trigger: Called from resolveEntry() after stat() resolves successfully. The path path.join(entry, relativeSource) resolves to a directory or special file rather than a regular file, so stat.isFile() is false.

Common situations: source field points to a folder name instead of a file inside it (e.g. "src" instead of "src/index.html"); accidentally created a directory with the same name as the intended entry file; pointing source at a node_modules package directory rather than its main file.

Related errors


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