{"record":{"id":"fe43785248478502","repo":"windmill-labs/windmill","slug":"not-found-fe4378","errorCode":null,"errorMessage":"not found","messagePattern":"not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"multiplayer/server.mjs","lineNumber":272,"sourceCode":"\n// --- HTTP + WebSocket server ---\n\nconst server = http.createServer((req, res) => {\n  // Strip /ws_mp/ prefix if present (when accessed without reverse proxy path stripping)\n  if (req.url?.startsWith('/ws_mp/')) {\n    req.url = req.url.slice('/ws_mp'.length)\n  } else if (req.url === '/ws_mp') {\n    req.url = '/'\n  }\n  console.log(`[${new Date().toISOString()}] HTTP ${req.method} ${req.url} from=${req.socket.remoteAddress}`)\n  if (req.url === '/' || req.url === '/health') {\n    res.writeHead(200, {\n      'Content-Type': 'application/json',\n      'Access-Control-Allow-Origin': '*'\n    })\n    res.end(JSON.stringify({ status: 'ok', service: 'multiplayer' }))\n  } else {\n    res.writeHead(404)\n    res.end('not found')\n  }\n})\n\nconst wss = new WebSocketServer({ server })\n\nwss.on('connection', async (ws, req) => {\n  let docName = req.url?.slice(1).split('?')[0] || 'unknown'\n\n  // Strip ws_mp/ prefix if present (when accessed without reverse proxy path stripping)\n  if (docName.startsWith('ws_mp/')) {\n    docName = docName.slice('ws_mp/'.length)\n  }\n\n  const clientIp = req.socket.remoteAddress\n\n  // Handle ping test — respond and close immediately\n  if (docName === '__ping__') {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/multiplayer/server.mjs#L254-L290","documentation":"multiplayer/server.mjs's HTTP handler only answers known routes (like the /health-style endpoint that returns { status: 'ok', service: 'multiplayer' }); anything else falls into the else branch which writes 404 and ends with the body 'not found'. It is the server's catch-all for unrecognized HTTP paths.","triggerScenarios":"An HTTP request hits the multiplayer server on a path that does not match any handled route — typo'd URL, wrong base path, request sent to the HTTP port instead of the WebSocket endpoint, or a health-check configured against a nonexistent path.","commonSituations":"Monitoring/probe pointed at the wrong path; client configured with an outdated route; someone curl-ing the health endpoint with a trailing typo (e.g. /heath); gateway forwarding paths the server does not implement.","solutions":["Check the requested path against the routes handled in multiplayer/server.mjs and correct the URL","If a health check, point it at the implemented status route that returns { status: 'ok', service: 'multiplayer' }","If a new route is needed, add it to the HTTP handler's if/else chain before the 404 fallback","Verify the request targets the multiplayer HTTP port, not the WebSocket-only path"],"exampleFix":"// before\nfetch('http://host:port/healthz')   // 404 'not found'\n// after\nfetch('http://host:port/health')    // 200 { status: 'ok', service: 'multiplayer' }","handlingStrategy":"validation","validationCode":"// verify the route exists before calling\nconst KNOWN_ROUTES = ['/health'];\nif (!KNOWN_ROUTES.includes(pathname)) throw new Error(`unknown multiplayer route: ${pathname}`);","typeGuard":null,"tryCatchPattern":"const res = await fetch(url);\nif (res.status === 404) {\n  const body = await res.text(); // 'not found'\n  throw new Error(`multiplayer server has no route for ${url.pathname}: ${body}`);\n}","preventionTips":["Keep the client's base URL/path list in sync with server.mjs routes","Point health checks at the route returning { status: 'ok', service: 'multiplayer' }","Don't send HTTP routes to the WebSocket endpoint port","Add a route table test that curls every documented path"],"tags":["http-404","routing","multiplayer","rest"],"backgroundTag":"http-404-not-found","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}