yikart/AiToEarn · error · AppException

ResponseCode.ConfigEditorRestartFailed

ResponseCode.ConfigEditorRestartFailed

Error message

ConfigEditorRestartFailed: error.message

What it means

restart() spawns `pm2 restart <pm_id>` via execFile; if spawning/execution throws synchronously (pm2 binary not on PATH, fork failure), the error is wrapped as AppException(ConfigEditorRestartFailed) with error.message. Note the callback-based execFile error (e.g. non-zero exit) is only logged, not thrown — this exception fires from the synchronous spawn path, typically 'spawn pm2 ENOENT'.

Source

Thrown at project/aitoearn-backend/libs/config-editor/src/config-restart.service.ts:23

@Injectable()
export class ConfigRestartService {
  private readonly logger = new Logger(ConfigRestartService.name)

  restart(): void {
    const pm2ProcessId = process.env['pm_id']
    if (!pm2ProcessId) {
      throw new AppException(ResponseCode.ConfigEditorPm2Unavailable)
    }

    try {
      const child = execFile('pm2', ['restart', pm2ProcessId], (error) => {
        if (error)
          this.logger.error(error)
      })
      child.unref()
    }
    catch (error) {
      throw new AppException(
        ResponseCode.ConfigEditorRestartFailed,
        error instanceof Error ? error.message : String(error),
      )
    }
  }
}

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Read error.message — 'spawn pm2 ENOENT' means install pm2 or add its global bin dir to PATH in the service environment
  2. Install pm2 in the image/runtime (`npm i -g pm2`) or reference the local node_modules/.bin/pm2
  3. Start pm2 and the app from the same environment so PATH matches; check with `which pm2` as the service user
  4. Consider replacing execFile('pm2') with process.exit() plus a pm2/systemd supervisor restart policy to avoid PATH dependence

Example fix

// before (Dockerfile)
CMD ["pm2-runtime", "app.js"]
RUN rm -rf /usr/local/lib/node_modules/pm2
// after
RUN npm i -g pm2 && pm2 install pm2-logrotate
CMD ["pm2-runtime", "app.js"]
Defensive patterns

Strategy: try-catch

Validate before calling

import { execFileSync } from 'node:child_process'
try { execFileSync('which', ['pm2']) } catch { throw new Error('pm2 binary not on PATH') }

Try / catch

try {
  restartService.restart()
} catch (e) {
  if (e instanceof AppException && e.code === ResponseCode.ConfigEditorRestartFailed && e.message.includes('ENOENT'))
    logger.error('pm2 binary missing from PATH in service environment')
  throw e
}

Prevention

When it happens

Trigger: pm_id exists but the `pm2` executable is not installed or not in the process's PATH (global npm bin missing, minimal container image, nvm PATH not loaded in the service's environment), or execFile throws synchronously for another spawn reason.

Common situations: App runs under pm2 via pm2-runtime but the pm2 CLI binary is absent in the runtime image; PATH differs between the shell that started pm2 and the service user; global npm prefix not in PATH under systemd/docker; permission to execute the binary missing.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/46c64532789cc2cb. Report an issue: GitHub.