The daemons entire log is discarded in any normally-launched build.
src/main/nobilis-process.ts pipes nobiliss stdout and stderr into src/main/log.ts, which writes with console.log. Started from a desktop entry, launcher or tray autostart there is no terminal on the other end — confirmed live on a running instance:
nobilis stdout -> socket:[1870851] (the pipe into Electron)
moho main stdout -> /dev/null (where it all ends up)
log.ts is written to survive that (it latches broken so an EIO cannot take the app down, which is correct and worth keeping) — but the consequence is that everything nobilis reports goes nowhere. That includes every line written to diagnose a problem after the fact:
scrollback: pruned N row(s) / pruning failed: — see #209, which had to be established by querying the database instead
realtime refused: from the Kick watch-time subscription in #206, which is the only signal that distinguishes a working subscription from a silently refused one
every backend reconnect, auth failure and protocol complaint
So when something goes wrong in the daemon — where essentially all the behaviour lives — there is no record of it on disk, and no way for a user to send one.
Suggested: a rolling log file under the data dir (e.g. ~/.config/nobilis/moho.log), size-capped with one previous generation kept, written by log.ts in addition to (or instead of) console. Everything needed is already funnelled through that one module, so this is a change in one place.
Found while investigating #209, where the absence of the log was what made the prune behaviour hard to establish.
The daemons entire log is discarded in any normally-launched build.
`src/main/nobilis-process.ts` pipes nobiliss stdout and stderr into `src/main/log.ts`, which writes with `console.log`. Started from a desktop entry, launcher or tray autostart there is no terminal on the other end — confirmed live on a running instance:
```
nobilis stdout -> socket:[1870851] (the pipe into Electron)
moho main stdout -> /dev/null (where it all ends up)
```
`log.ts` is written to survive that (it latches `broken` so an EIO cannot take the app down, which is correct and worth keeping) — but the consequence is that everything nobilis reports goes nowhere. That includes every line written to diagnose a problem after the fact:
- `scrollback: pruned N row(s)` / `pruning failed:` — see #209, which had to be established by querying the database instead
- `realtime refused:` from the Kick watch-time subscription in #206, which is the only signal that distinguishes a working subscription from a silently refused one
- every backend reconnect, auth failure and protocol complaint
So when something goes wrong in the daemon — where essentially all the behaviour lives — there is no record of it on disk, and no way for a user to send one.
Suggested: a rolling log file under the data dir (e.g. `~/.config/nobilis/moho.log`), size-capped with one previous generation kept, written by `log.ts` in addition to (or instead of) console. Everything needed is already funnelled through that one module, so this is a change in one place.
Found while investigating #209, where the absence of the log was what made the prune behaviour hard to establish.
Salastil
added the bug label 2026-09-12 17:09:14 -04:00
log.ts now writes every line to a file as well as to console: 4MB, one previous generation kept (moho.log, moho.log.1), written synchronously - the line most worth having is the last one before a crash, and a queued async write is the one that does not make it.
The stdout latch stays exactly as it was, and the file write happens before it is consulted, so a console that throws EIO no longer means silence everywhere.
One deviation from the suggestion: it goes in the app's own userData directory rather than the daemon's data dir. The client does not know that path - it spawns nobilis without --data-dir and lets the daemon resolve its own, XDG rules and legacy fallbacks included - so writing there would mean reimplementing the daemon's path logic in the client and being wrong the day it changes. Given #208, duplicating a path between those two processes is a mistake worth not repeating.
log.ts still imports no electron; the directory is passed in at startup. That keeps its rotation testable, and it is tested: daemon lines land, levels and ISO timestamps are recorded, an object argument and an Error's stack both survive, it rotates at the cap keeping one generation, and with console.log made to throw EIO the latch trips while the file still gets the line.
It takes effect on the next start of the client - the log will be at ~/.config/moho/moho.log, and the first line names its own path.
Finished in [`f2fc66f`](https://git.salastil.com/Salastil/moho/commit/f2fc66f).
`log.ts` now writes every line to a file as well as to console: 4MB, one previous generation kept (`moho.log`, `moho.log.1`), written synchronously - the line most worth having is the last one before a crash, and a queued async write is the one that does not make it.
The stdout latch stays exactly as it was, and the file write happens **before** it is consulted, so a console that throws EIO no longer means silence everywhere.
One deviation from the suggestion: it goes in the app's own userData directory rather than the daemon's data dir. The client does not know that path - it spawns nobilis without `--data-dir` and lets the daemon resolve its own, XDG rules and legacy fallbacks included - so writing there would mean reimplementing the daemon's path logic in the client and being wrong the day it changes. Given #208, duplicating a path between those two processes is a mistake worth not repeating.
`log.ts` still imports no electron; the directory is passed in at startup. That keeps its rotation testable, and it is tested: daemon lines land, levels and ISO timestamps are recorded, an object argument and an `Error`'s stack both survive, it rotates at the cap keeping one generation, and with `console.log` made to throw EIO the latch trips while the file still gets the line.
It takes effect on the next start of the client - the log will be at `~/.config/moho/moho.log`, and the first line names its own path.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The daemons entire log is discarded in any normally-launched build.
src/main/nobilis-process.tspipes nobiliss stdout and stderr intosrc/main/log.ts, which writes withconsole.log. Started from a desktop entry, launcher or tray autostart there is no terminal on the other end — confirmed live on a running instance:log.tsis written to survive that (it latchesbrokenso an EIO cannot take the app down, which is correct and worth keeping) — but the consequence is that everything nobilis reports goes nowhere. That includes every line written to diagnose a problem after the fact:scrollback: pruned N row(s)/pruning failed:— see #209, which had to be established by querying the database insteadrealtime refused:from the Kick watch-time subscription in #206, which is the only signal that distinguishes a working subscription from a silently refused oneSo when something goes wrong in the daemon — where essentially all the behaviour lives — there is no record of it on disk, and no way for a user to send one.
Suggested: a rolling log file under the data dir (e.g.
~/.config/nobilis/moho.log), size-capped with one previous generation kept, written bylog.tsin addition to (or instead of) console. Everything needed is already funnelled through that one module, so this is a change in one place.Found while investigating #209, where the absence of the log was what made the prune behaviour hard to establish.
Finished in
f2fc66f.log.tsnow writes every line to a file as well as to console: 4MB, one previous generation kept (moho.log,moho.log.1), written synchronously - the line most worth having is the last one before a crash, and a queued async write is the one that does not make it.The stdout latch stays exactly as it was, and the file write happens before it is consulted, so a console that throws EIO no longer means silence everywhere.
One deviation from the suggestion: it goes in the app's own userData directory rather than the daemon's data dir. The client does not know that path - it spawns nobilis without
--data-dirand lets the daemon resolve its own, XDG rules and legacy fallbacks included - so writing there would mean reimplementing the daemon's path logic in the client and being wrong the day it changes. Given #208, duplicating a path between those two processes is a mistake worth not repeating.log.tsstill imports no electron; the directory is passed in at startup. That keeps its rotation testable, and it is tested: daemon lines land, levels and ISO timestamps are recorded, an object argument and anError's stack both survive, it rotates at the cap keeping one generation, and withconsole.logmade to throw EIO the latch trips while the file still gets the line.It takes effect on the next start of the client - the log will be at
~/.config/moho/moho.log, and the first line names its own path.