fix(http): 400 on malformed JSON body instead of 500
Build and Deploy Remote Control Support / Test (push) Successful in 11s
Build and Deploy Remote Control Support / Build Image (push) Successful in 47s
Build and Deploy Remote Control Support / Deploy to Portainer (push) Successful in 7s

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 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 23:55:48 -07:00
co-authored by Claude Opus 5
parent 30feb5f61b
commit 88be2bf867
2 changed files with 15 additions and 2 deletions
+12 -2
View File
@@ -140,10 +140,20 @@ Both are revocable, expiring, and logged.
72 assertions covering auth, RBAC, VNC auth, view-only, invites, agent tunnel 72 assertions covering auth, RBAC, VNC auth, view-only, invites, agent tunnel
### Phase 7 — Front end polish ### Phase 7 — Front end polish
- [~] Modern visual design pass across all five pages - [x] Modern visual design pass across all five pages
- [~] Particle background (network-of-machines motif), reduced-motion aware, - [x] Particle background (network-of-machines motif), reduced-motion aware,
never rendered behind a live VNC canvas 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 ### Phase 8 — Later / nice to have
- [ ] File transfer between operator and client - [ ] File transfer between operator and client
- [ ] Clipboard sync toggle per session - [ ] Clipboard sync toggle per session
+3
View File
@@ -81,6 +81,9 @@ app.use((req, res) => {
// eslint-disable-next-line no-unused-vars -- Express identifies error handlers by arity // eslint-disable-next-line no-unused-vars -- Express identifies error handlers by arity
app.use((err, req, res, _next) => { 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); console.error('[http]', err);
res.status(500).json({ error: 'internal error' }); res.status(500).json({ error: 'internal error' });
}); });