From 9329fe0e2ae6381b8fbbf1302306c4db036880a4 Mon Sep 17 00:00:00 2001 From: Adam Jones Date: Wed, 15 Apr 2026 15:21:00 +0000 Subject: [PATCH] Don't crash the agent if prismarine-viewer can't bind its port mineflayerViewer() creates an http server on 3000+count_id but doesn't expose it, so EADDRINUSE (e.g. something already on :3000, or two agents racing) becomes an uncaught exception that kills the agent process. Probe the port first and fall back to a warning + no viewer. --- src/agent/vision/browser_viewer.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/agent/vision/browser_viewer.js b/src/agent/vision/browser_viewer.js index 6cce3ed03..ebe1e9982 100644 --- a/src/agent/vision/browser_viewer.js +++ b/src/agent/vision/browser_viewer.js @@ -1,8 +1,31 @@ import settings from '../settings.js'; +import http from 'http'; import prismarineViewer from 'prismarine-viewer'; const mineflayerViewer = prismarineViewer.mineflayer; export function addBrowserViewer(bot, count_id) { - if (settings.render_bot_view) - mineflayerViewer(bot, { port: 3000+count_id, firstPerson: true, }); -} \ No newline at end of file + if (!settings.render_bot_view) return; + const port = 3000 + count_id; + + const fail = (err) => { + console.warn(`prismarine-viewer failed on port ${port}: ${err.message}. Continuing without viewer.`); + }; + + // mineflayerViewer creates its own http server and never exposes it, so a + // listen failure (e.g. EADDRINUSE) surfaces as an unhandled 'error' event + // that kills the process. Hook createServer just long enough to attach an + // error listener to that server. + const origCreateServer = http.createServer; + http.createServer = (...args) => { + const server = origCreateServer(...args); + server.on('error', fail); + return server; + }; + try { + mineflayerViewer(bot, { port, firstPerson: true }); + } catch (err) { + fail(err); + } finally { + http.createServer = origCreateServer; + } +}