{"record":{"id":"ac449fe6ba1ed9c8","repo":"mjmlio/mjml","slug":"cannot-read-file-path-doesn-t-exist-or-no-acce","errorCode":null,"errorMessage":"Cannot read file: ${path} doesn't exist or no access","messagePattern":"Cannot read file: (.+?) doesn't exist or no access","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mjml-cli/src/commands/readFile.js","lineNumber":13,"sourceCode":"import fs from 'fs'\nimport { sync } from 'glob'\nimport { flatMap } from 'lodash'\n\nexport const flatMapPaths = (paths) =>\n  flatMap(paths, (p) => sync(p, { nodir: true }))\n\nexport default (path) => {\n  try {\n    return { file: path, mjml: fs.readFileSync(path).toString() }\n  } catch (e) {\n    // eslint-disable-next-line\n    console.warn(`Cannot read file: ${path} doesn't exist or no access`, e)\n    return {}\n  }\n}\n","sourceCodeStart":1,"sourceCodeEnd":17,"githubUrl":"https://github.com/mjmlio/mjml/blob/6c01d35af5da14108b86bbf052232e99de7ca755/packages/mjml-cli/src/commands/readFile.js#L1-L17","documentation":"readFile attempts fs.readFileSync(path) and, when the file cannot be read (missing file, no permission, it is a directory), warns 'Cannot read file: <path> doesn't exist or no access' and returns an empty object instead of throwing. The CLI then typically treats this as a missing/empty input.","triggerScenarios":"Calling readFile('/some/path') where the file does not exist, the path is a directory, or the process lacks read permission. Any fs.readFileSync throw (ENOENT, EACCES, EISDIR) lands in this catch.","commonSituations":"Typo in the CLI input filename; globbing produced no matches and a literal pattern was passed; running in a container/CI where the template file was not copied or lacks permissions; wrong working directory.","solutions":["Verify the path exists and is a regular file: ls -l <path>, and check permissions","Run the CLI from the correct working directory or use absolute paths","Fix CI/package steps so template files are included and readable in the environment","If consuming readFile programmatically, check the returned object for a truthy mjml property before rendering"],"exampleFix":"// before\nmjml emails/invite.mjml   // ENOENT: file not copied\n// after\nmjml src/templates/invite.mjml --config.includePath src/templates/partials\n// programmatic guard\nconst { mjml } = readFile(p)\nif (!mjml) { throw new Error(`Input missing: ${p}`) }","handlingStrategy":"validation","validationCode":"import fs from 'fs'\nconst canRead = (p) => { try { return fs.statSync(p).isFile() } catch { return false } }\nif (!canRead(inputPath)) throw new Error(`Input file missing or unreadable: ${inputPath}`)","typeGuard":"const isReadableFile = (p) => { try { return typeof p === 'string' && fs.statSync(p).isFile() } catch { return false } }","tryCatchPattern":"const { mjml } = readFile(p)\nif (!mjml) {\n  // readFile swallows the error and returns {}\n  throw new Error(`Failed to read input: ${p}`)\n}","preventionTips":["Verify paths exist with fs.statSync before rendering","Use absolute paths (path.resolve) in scripts/CI","Check file permissions in containers (COPY with correct owner)","Treat an empty readFile return object as an error condition"],"tags":["filesystem","enoent","file-not-found","permissions","mjml-cli"],"backgroundTag":"file-not-found","analyzedSha":"6c01d35af5da14108b86bbf052232e99de7ca755","analyzedAt":"2026-09-02T21:31:03.649Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}