From 2173b5ab8fd649dee4886b8983e55c88375324c4 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Tue, 8 Sep 2026 22:39:59 -0400 Subject: [PATCH] fix: handle mysql2 >=3.23 returning JSON columns pre-parsed mysql2 3.24 (pulled in by the audit fix in #35) returns MariaDB JSON columns as JS objects. GET /api/internal/executions/:id and GET /api/workflows/:id still called JSON.parse on the value, threw, and silently returned [] / {}. This broke Gandalf's relay checks (false 'PBS unreachable' ticket) and the workflow edit modal. Guard both sites with the same typeof check already used by GET /api/executions/:id. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01HamVMDrA8RqhyxmUHgiqRp --- server.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/server.js b/server.js index ac699f7..39d2f2c 100644 --- a/server.js +++ b/server.js @@ -1194,7 +1194,11 @@ app.get('/api/workflows/:id', authenticateSSO, async (req, res) => { if (rows.length === 0) return res.status(404).json({ error: 'Not found' }); const wf = rows[0]; let definition = {}; - try { definition = JSON.parse(wf.definition || '{}'); } catch { /* corrupt definition — return empty */ } + try { + definition = typeof wf.definition === 'string' + ? JSON.parse(wf.definition || '{}') + : (wf.definition || {}); + } catch { /* corrupt definition — return empty */ } res.json({ ...wf, definition }); } catch (error) { console.error('[API] GET /api/workflows/:id error:', error); @@ -1659,7 +1663,11 @@ app.get('/api/internal/executions/:id', authenticateGandalf, async (req, res) => } const execution = rows[0]; let logs = []; - try { logs = JSON.parse(execution.logs || '[]'); } catch { logs = []; } + try { + logs = typeof execution.logs === 'string' + ? JSON.parse(execution.logs || '[]') + : (execution.logs || []); + } catch { logs = []; } res.json({ ...execution, logs }); } catch (error) { console.error('[API] GET /api/internal/executions/:id error:', error); -- 2.47.3