facebook/docusaurus · error · Error

You specified ${source}, but file at path path=${filepath} c

Error message

You specified ${source}, but file at path path=${filepath} can't be read.

What it means

Thrown by readCryptoFile() when the SSL cert/key file DOES exist (fs.pathExists passed) but fs.readFile() rejects while reading its bytes. The original IO error is attached via `{cause: error}` on the thrown Error so the underlying reason (EACCES, EISDIR, disk read failure) is preserved. The {source} placeholder again tells you which input supplied the path.

Source

Thrown at packages/docusaurus/src/webpack/utils/getHttpsConfig.ts:89

};

async function readCryptoFile(
  filepath: string,
  source: string,
): Promise<CryptoFile> {
  if (!(await fs.pathExists(filepath))) {
    throw new Error(
      logger.interpolate`You specified ${source}, but file at path path=${filepath} can't be found.`,
    );
  }
  try {
    return {
      path: filepath,
      source,
      content: await fs.readFile(filepath),
    };
  } catch (error) {
    throw new Error(
      logger.interpolate`You specified ${source}, but file at path path=${filepath} can't be read.`,
      {cause: error},
    );
  }
}

function getCert(
  options: Partial<HttpsConfigOptions>,
  cwd: string,
): Promise<CryptoFile> | null {
  if (options.sslCert) {
    return readCryptoFile(
      path.resolve(cwd, options.sslCert),
      'CLI arg --ssl-cert',
    );
  }
  if (process.env.DOCUSAURUS_SSL_CRT_FILE) {
    return readCryptoFile(

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Inspect the `cause` on the thrown error — it carries the real errno (EACCES, EISDIR, ENOENT-on-symlink) which tells you the fix.
  2. Confirm the path is a regular file, not a directory: `test -f "<path>" && file "<path>"`.
  3. Fix permissions so the Node process can read it: `chmod 644 <cert> <key>` (and ensure the user running the CLI owns or can read them).
  4. If it is a symlink, resolve it and point directly at the real file, or recreate the target.

Example fix

// before: --ssl-cert points at a dir / unreadable file
docusaurus start --https --ssl-cert ./certs
// after: point at the readable regular file
chmod 644 ./certs/server.crt
docusaurus start --https --ssl-cert ./certs/server.crt
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'fs-extra';
import path from 'path';

async function assertCryptoFileReadable(rawPath: string, cwd = process.cwd()) {
  const abs = path.resolve(cwd, rawPath);
  const stat = await fs.stat(abs);
  if (!stat.isFile()) throw new Error(`${abs} is not a regular file`);
  await fs.access(abs, fs.constants.R_OK); // throws EACCES if unreadable
  return abs;
}

Try / catch

try {
  await getHttpsConfig({ https: true, sslCert, sslKey });
} catch (err) {
  // err.cause carries the real errno (EACCES/EISDIR) from fs.readFile
  if (err.cause?.code === 'EACCES') {
    console.error('Fix file permissions on the SSL cert/key.');
  }
  throw err;
}

Prevention

When it happens

Trigger: The cert/key path resolves to a directory rather than a file; the file exists but the Node process lacks read permission (EACCES); the file is on a mount that became unreadable; a symlink points to a missing/broken target that pathExists followed but read cannot complete.

Common situations: Pointing --ssl-cert at a directory by mistake; certs created by root/root and the dev process runs as a non-privileged user without read access; copied a broken symlink into the certs folder; file locked or being written by another process on Windows.

Related errors


AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12). Data as JSON: /api/errors/bbb1ac3fafa7bb5f. Report an issue: GitHub.