mjmlio/mjml · error · Error

Specified filePath does not exist

Error message

Specified filePath does not exist

What it means

mjml-cli's fileContext helper resolves the directory containing an input file by lstat-ing the given filePath. If the path cannot be stat-ed at all (fs.lstatSync throws ENOENT), the helper re-throw a clearer Error('Specified filePath does not exist') instead of leaking the raw ENOENT. It is a guard against running mjml CLI commands on a file or directory path that is not on disk.

Source

Thrown at packages/mjml-cli/src/helpers/fileContext.js:23

  /<mj-include[^<>]+path=['"](.*(?:\.mjml|\.css|\.html))['"]\s*[^<>]*(\/>|>\s*<\/mj-include>)/gi

const ensureIncludeIsSupportedFile = (file) =>
  path.extname(file).match(/\.mjml|\.css|\.html/) ? file : `${file}.mjml`

const error = (e) => console.error(e.stack || e) // eslint-disable-line no-console

export default (baseFile, filePath) => {
  const filesIncluded = []

  let filePathDirectory = ''
  if (filePath) {
    try {
      const isFilePathDir = fs.lstatSync(filePath).isDirectory()

      filePathDirectory = isFilePathDir ? filePath : path.dirname(filePath)
    } catch (e) {
      if (e.code === 'ENOENT') {
        throw new Error('Specified filePath does not exist')
      } else {
        throw e
      }
    }
  }

  const readIncludes = (dir, file, base) => {
    const currentFile = path.resolve(
      dir
        ? path.join(dir, ensureIncludeIsSupportedFile(file))
        : ensureIncludeIsSupportedFile(file),
    )

    const currentDirectory = path.dirname(currentFile)

    const includes = new RegExp(includeRegexp)

    let content

View on GitHub (pinned to 6c01d35af5)

Solutions

  1. Verify the path exists with ls/test -f before invoking mjml and correct typos.
  2. Run the command from the directory containing the file, or pass an absolute path.
  3. If the file is build-generated, ensure the preceding build step ran and produced it.
  4. Wrap the mjml invocation in a check like fs.existsSync(filePath) in scripts.

Example fix

// before
mjml ./template.mjml -o ./out.html   // ENOENT: template.mjml missing
// after
ls ./template.mjml                   # confirm it exists / fix the path
mjml ./templates/newsletter.mjml -o ./out.html
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
if (!fs.existsSync(filePath)) throw new Error(`Input not found: ${filePath}`);

Try / catch

try {
  runMjmlCli(args)
} catch (e) {
  if (e.message === 'Specified filePath does not exist') {
    console.error(`Path not found: ${args[0]}. cwd=${process.cwd()}`)
    process.exit(1)
  }
  throw e
}

Prevention

When it happens

Trigger: Running a CLI command that resolves a file context (e.g. mjml --watch or compile helpers) with an input/output path that does not exist; passing a relative path from a different working directory; a glob or config pointing at a deleted/moved file.

Common situations: Typo in the mjml file name on the command line; running mjml before the input file is generated by a build step; a watch configuration referencing a file that was renamed or deleted; wrong cwd when using relative paths in scripts or CI.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of mjmlio/mjml@6c01d35af5 (2026-09-02). Data as JSON: /api/errors/b5e51850de508515. Report an issue: GitHub.