Tower Restart Loop on Daily Purge Cron + Cron Resilience
Version: 3.1.0 Date: 2026-06-12
Goal: Stop the nightly restart loop observed on Towers stuck in need_configuration. The 3 AM purge cron raised an unhandled rejection (ENOENT '/data/work') that killed the Node process. More broadly, several crons and FS code paths were fragile to a Tower that had never been configured.
Solution:
AppController.purge()is nowasyncand awaitsDataService.purgeWork()so rejections fall into thetry/catch.DataService.purgeWork()early-returns ifworkFolderdoes not exist;onModuleInit()createsworkFolder(/data/work) at boot.LoggerServiceusesmkdirSync(logDir, { recursive: true }).loadState()andgetTask()no longer rely onflag: 'a+'to create files on read — ENOENT is handled explicitly.SourcesService.discover(),TaskService.run(),TaskService.moveWaitingTaskToQueued()early-return when the Tower has no config;purgestays scheduled but is now safe.main.tsregisters globalunhandledRejection(log + swallow) anduncaughtException(log + clean exit) handlers;bootstrap()is awaited with a.catch.- Audit of
LoggerService.error(msg, error)misuses: 8 FTP-side call sites passed an Error in theid: stringparameter, fixed to(msg, null, error)(ortask.uuidwhen available).
Bug Fixes:
- Tower no longer restarts at 3 AM when not yet configured —
purge()awaits its async work,purgeWorktolerates a missing folder,workFoldercreated at boot. - Idle crons no longer run on unconfigured Towers —
discover,run,moveWaitingTaskToQueuedgated byConfigurationService.hasConfig().
Improvements:
- Process-level error handlers + clean container restart —
unhandledRejection/uncaughtExceptionhandlers inmain.ts. - LoggerService.error signature usage audit — 8 FTP-related call sites fixed to the canonical
error(msg, null, error)signature.
Files Modified:
src/app.controller.ts-purge()async, awaitspurgeWork(), logger signature correctedsrc/core/data/data.service.ts-purgeWork()early-return;onModuleInit()createsworkFolder; explicit ENOENT handling inloadState()/getTask()src/protocol/source/source.service.ts-discover()early-returns when no config; correct error loggingsrc/core/task/task.service.ts-run()andmoveWaitingTaskToQueued()early-return when no configsrc/core/task/task.service.spec.ts-hasConfigsetup + 2 "no config → no-op" testssrc/main.ts-registerProcessErrorHandlers(logger),bootstrap()wrapped with.catchsrc/protocol/source/ftp/ftp.service.ts- error log signaturesrc/protocol/storage/ftp/ftp.storage.service.ts-task.uuidasid,easdatasrc/protocol/capacities/ftp-capacity/ftp-capacity.service.ts- 6 sites fixed to(msg, null, e)src/core/logger/logger.service.ts-mkdirSyncuses{ recursive: true }src/core/initialization/initialization.service.ts- fixed typo + duplicated job name in log