Where: LIFEOS/PULSE/modules/telegram.ts:746-756 + LIFEOS/PULSE/pulse.ts:362-377 (supervise())
What happens: startTelegram() returns cleanly (no throw) when no bot token is configured:
const token = config.bot_token ?? process.env.TELEGRAM_BOT_TOKEN
if (!token) {
log("error", "No bot token — set bot_token in config or TELEGRAM_BOT_TOKEN in env")
return
}
The generic subsystem supervisor in pulse.ts treats any clean return as a normal exit and just restarts it on a flat 10s timer, forever:
async function supervise(name: string, fn: () => Promise<void>, shuttingDown: () => boolean) {
while (!shuttingDown()) {
try {
await fn()
if (!shuttingDown()) {
log("info", `${name} exited cleanly, restarting in 10s`)
await Bun.sleep(10_000)
}
} catch (err) { ... }
}
}
There's no cap and no backoff for this path — MAX_FAILURES/MAX_SLEEP_MS/MIN_SLEEP_MS exist in the same file but are only wired into the cron-job scheduler, not supervise().
Impact (observed): With [telegram] enabled = true in PULSE.toml and no TELEGRAM_BOT_TOKEN set anywhere, the process logged "telegram exited cleanly, restarting in 10s" continuously (3,000+ occurrences over ~2 days), and pulse.ts sustained ~70-75% CPU the whole time.
Suggested fix: either (a) have startTelegram throw/signal a config error distinct from a clean shutdown, so supervise() can apply backoff or give up after MAX_FAILURES, or (b) have the module self-disable (log once, return without re-registering) when required config is missing rather than exiting-to-be-restarted.
Workaround used: set [telegram] enabled = false in PULSE.toml until a token is configured.
Where:
LIFEOS/PULSE/modules/telegram.ts:746-756+LIFEOS/PULSE/pulse.ts:362-377(supervise())What happens:
startTelegram()returns cleanly (no throw) when no bot token is configured:The generic subsystem supervisor in
pulse.tstreats any clean return as a normal exit and just restarts it on a flat 10s timer, forever:There's no cap and no backoff for this path —
MAX_FAILURES/MAX_SLEEP_MS/MIN_SLEEP_MSexist in the same file but are only wired into the cron-job scheduler, notsupervise().Impact (observed): With
[telegram] enabled = trueinPULSE.tomland noTELEGRAM_BOT_TOKENset anywhere, the process logged "telegram exited cleanly, restarting in 10s" continuously (3,000+ occurrences over ~2 days), andpulse.tssustained ~70-75% CPU the whole time.Suggested fix: either (a) have
startTelegramthrow/signal a config error distinct from a clean shutdown, sosupervise()can apply backoff or give up afterMAX_FAILURES, or (b) have the module self-disable (log once, return without re-registering) when required config is missing rather than exiting-to-be-restarted.Workaround used: set
[telegram] enabled = falseinPULSE.tomluntil a token is configured.