From 88be2bf8674f65c703df936501b9996966a8d4f1 Mon Sep 17 00:00:00 2001 From: Ricardo Mancinas Date: Tue, 11 Aug 2026 23:55:48 -0700 Subject: [PATCH] fix(http): 400 on malformed JSON body instead of 500 express.json() raising a parse error was falling through to the generic 500 handler, which reads as a server fault for what is a bad request. Also maps the body-size limit to 413. Co-Authored-By: Claude Opus 5 --- PLAN.md | 14 ++++++++++++-- server/index.js | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/PLAN.md b/PLAN.md index c550756..8bed516 100644 --- a/PLAN.md +++ b/PLAN.md @@ -140,10 +140,20 @@ Both are revocable, expiring, and logged. 72 assertions covering auth, RBAC, VNC auth, view-only, invites, agent tunnel ### Phase 7 — Front end polish -- [~] Modern visual design pass across all five pages -- [~] Particle background (network-of-machines motif), reduced-motion aware, +- [x] Modern visual design pass across all five pages +- [x] Particle background (network-of-machines motif), reduced-motion aware, never rendered behind a live VNC canvas +### Deployed +Live at `http://192.168.4.212:5910` (Swarm ingress). Published port is 5910, not +8091 — 8091 is reserved on the ingress by `ai-training-lab_ai-lab`, and that +reservation holds even while nothing answers on it, so probing the port cannot +tell you it is taken. Only the Swarm's own view is authoritative. + +Remaining to be usable from outside the LAN console: +- [ ] `support.freakma.com` DNS + Nginx Proxy Manager host, **WebSocket support on** +- [ ] First machine enrolled + ### Phase 8 — Later / nice to have - [ ] File transfer between operator and client - [ ] Clipboard sync toggle per session diff --git a/server/index.js b/server/index.js index 6c792ce..3304dc8 100644 --- a/server/index.js +++ b/server/index.js @@ -81,6 +81,9 @@ app.use((req, res) => { // eslint-disable-next-line no-unused-vars -- Express identifies error handlers by arity app.use((err, req, res, _next) => { + // A body express.json() could not parse is the caller's fault, not ours. + if (err.type === 'entity.parse.failed') return res.status(400).json({ error: 'malformed JSON body' }); + if (err.type === 'entity.too.large') return res.status(413).json({ error: 'request body too large' }); console.error('[http]', err); res.status(500).json({ error: 'internal error' }); });