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
- Read error.message — 'spawn pm2 ENOENT' means install pm2 or add its global bin dir to PATH in the service environment
- Install pm2 in the image/runtime (`npm i -g pm2`) or reference the local node_modules/.bin/pm2
- Start pm2 and the app from the same environment so PATH matches; check with `which pm2` as the service user
- 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
- Install pm2 globally (or vendor it) in runtime images
- Start pm2 and the app from the same shell/PATH environment
- Check `which pm2` as the exact service user, not just interactively
- Prefer supervisor-based restart policies over shelling out to pm2 where possible
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.