Files
open-design/apps/packaged
lefarcenandGitHub 2e377a5152 name every packaged startup failure instead of bucketing it as unknown (#5956)
* name every packaged startup failure instead of bucketing it as unknown

The weekly `packaged_runtime_failed` alert is dominated by failures the event
had enough evidence to name and reported as opaque anyway. Triaging a 7d window
turned up three places where the emitter threw away a cause it was already
holding:

- 62 devices died with the daemon log tail read successfully, but
  `parseDaemonLogTail` only ever matched `ERR_*`. A daemon that threw anything
  else (SQLite corruption, EPERM, a plain throw) reported error_code=null AND
  missing_module=null with its reason printed in the tail we had just read.
- 21 devices hit win32 CreateProcess failures. Node puts the real cause on the
  error's `code`/`errno`/`syscall`; the event sent `.message` only, so
  `spawn UNKNOWN` was indistinguishable from any other opaque failure.
- 149 devices produced an Error with an empty `.message` and no `.stack`. Every
  free-form field went null, leaving residue that could not even be counted
  apart from "no error at all".

So: parse the sidecar's own fatal line as a backstop when `ERR_*` misses, carry
the errno triplet off the thrown object, classify a rejected spawn as its own
`spawn-failed` kind rather than `unknown`, and guarantee a thrown error never
serializes to error_message=null — an unnamed leftover is now a named, countable
bucket.

Classification-only; the failures themselves are unchanged. Every test input is
a verbatim field payload from the alert window.

* reduce syscall to its operation token before sending it

Review catch, and a real leak. Node does not guarantee `syscall` holds only the
operation name: spawning a missing binary sets it to the whole invocation.
Verified against real Node —

  spawn('/Users/elian/nonexistent/bin/thing')
    → syscall === 'spawn /Users/elian/nonexistent/bin/thing'

Forwarding that verbatim would have put the local username and install path
into an event that is retained even for opted-out users, while every other path
this module sends goes through scrubUserPaths.

Keep the first token — the operation is the whole analytic value, and the path
is already available (scrubbed) via error_message — then scrub what survives
and cap it, as a second line of defence. `code` is capped too.

This also fixes a classification miss the same review implies: the spawn-failed
branch compared the RAW syscall to 'spawn', so a spawn error carrying a path
never matched and fell through to `unknown` — the exact bucket this PR exists
to drain.
2026-07-22 06:20:33 +00:00
..

apps/packaged

Thin packaged Electron runtime entry for Open Design.

This package starts the packaged daemon and web sidecars, registers the od:// entry protocol, and then delegates to @open-design/desktop/main for the host window. Product logic stays in apps/daemon, apps/web, and apps/desktop.