Unitech/pm2 · error · Error

Could not create folder

Error message

Could not create folder

What it means

When PM2 resolves out_file / error_file / log file paths for an app, it ensures the parent directory exists by calling fs.mkdirSync(dir, {recursive:true}). If that call throws (permission denied, read-only filesystem, invalid path, disk full), the error is surfaced as 'Could not create folder'.

Source

Thrown at lib/Common.js:220

  ['log', 'out', 'error', 'pid'].forEach(function(f){
    var af = app[f + '_file'], ps, ext = (f == 'pid' ? 'pid':'log'), isStd = !~['log', 'pid'].indexOf(f);
    if (af) af = resolveHome(af);

    if ((f == 'log' && typeof af == 'boolean' && af) || (f != 'log' && !af)) {
      ps = [cst['DEFAULT_' + ext.toUpperCase() + '_PATH'], formated_app_name + (isStd ? '-' + f : '') + '.' + ext];
    } else if ((f != 'log' || (f == 'log' && af)) && af !== 'NULL' && af !== '/dev/null') {
      ps = [cwd, af];

      var dir = path.dirname(path.resolve(cwd, af));
      if (!fs.existsSync(dir)) {
        Common.printError(cst.PREFIX_MSG_WARNING + 'Folder does not exist: ' + dir);
        Common.printOut(cst.PREFIX_MSG + 'Creating folder: ' + dir);
        try {
          fs.mkdirSync(dir, { recursive: true });
        } catch (err) {
          Common.printError(cst.PREFIX_MSG_ERR + 'Could not create folder: ' + path.dirname(af));
          throw new Error('Could not create folder');
        }
      }

    }
    // PM2 paths
    if (af !== 'NULL' && af !== '/dev/null') {
      ps && (app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = path.resolve.apply(null, ps));
    } else if (path.sep === '\\') {
      app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = '\\\\.\\NUL';
    } else {
      app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = '/dev/null';
    }
    delete app[f + '_file'];
  });

  return app;
};

View on GitHub (pinned to 31adee8048)

Solutions

  1. Point log paths to a directory the PM2 daemon user can write to.
  2. Pre-create the log directory and grant write access to the daemon user.
  3. Drop the out_file/error_file overrides so PM2 uses its default log location under PM2_HOME.

Example fix

// before
out_file: '/var/log/myapp/out.log'
// after
out_file: '/home/app/logs/out.log'
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('fs');
const path = require('path');
function ensureLogDir(file) {
  const dir = path.dirname(path.resolve(file));
  try { fs.mkdirSync(dir, { recursive: true }); return true; }
  catch (e) { return false; }
}
if (!ensureLogDir(app.out_file) || !ensureLogDir(app.error_file)) {
  delete app.out_file; delete app.error_file; // fall back to PM2 defaults
}

Try / catch

try {
  pm2.start(app, cb);
} catch (e) {
  if (/Could not create folder/.test(e.message)) {
    delete app.out_file; delete app.error_file;
    pm2.start(app, cb);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Configuring an app with out_file/error_file pointing into a directory PM2 cannot create — unwritable location, read-only rootfs, Windows invalid drive, or a path the daemon user can't write to.

Common situations: Apps run as a low-privilege user that logs into /var/log without write permission; containers with a read-only root filesystem; path typos; log dir on an unmounted volume.


AI-assisted analysis of Unitech/pm2@31adee8048 (2026-08-13). Data as JSON: /api/errors/ae87b8f1de74c47b. Report an issue: GitHub.