{"record":{"id":"8f99ef995c45d200","repo":"different-ai/openwork","slug":"could-not-start-openwork-ui-control-bridge","errorCode":null,"errorMessage":"Could not start OpenWork UI control bridge.","messagePattern":"Could not start OpenWork UI control bridge\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/ui-control-server.mjs","lineNumber":167,"sourceCode":"          return;\n        }\n        if (request.method === \"POST\" && url.pathname === \"/execute\") {\n          sendJsonResponse(response, 200, await runOpenworkControlCommand(\"execute\", await readJsonRequestBody(request)));\n          return;\n        }\n        sendJsonResponse(response, 404, { ok: false, error: \"Not found\" });\n      } catch (error) {\n        console.error(\"[ui-control] request failed\", error);\n        sendJsonResponse(response, 500, { ok: false, error: \"OpenWork UI control request failed.\" });\n      }\n    });\n    await new Promise((resolve, reject) => {\n      uiControlServer.once(\"error\", reject);\n      uiControlServer.listen(0, \"127.0.0.1\", () => resolve(undefined));\n    });\n    const address = uiControlServer.address();\n    const port = typeof address === \"object\" && address ? address.port : null;\n    if (!port) throw new Error(\"Could not start OpenWork UI control bridge.\");\n    uiControlDiscoveryPath = path.join(app.getPath(\"userData\"), \"openwork-ui-control.json\");\n    await writeFile(\n      uiControlDiscoveryPath,\n      `${JSON.stringify({ version: 2, app: appName, identifier: appIdentifier, platform: process.platform, baseUrl: `http://127.0.0.1:${port}`, token: uiControlToken }, null, 2)}\\n`,\n      \"utf8\",\n    );\n    // Make the discovery path available to child processes (server → managed OpenCode → plugin).\n    process.env.OPENWORK_UI_CONTROL_DISCOVERY = uiControlDiscoveryPath;\n  }\n\n  async function stop() {\n    if (uiControlDiscoveryPath) {\n      await rm(uiControlDiscoveryPath, { force: true }).catch(() => undefined);\n      uiControlDiscoveryPath = null;\n    }\n    if (!uiControlServer) return;\n    await new Promise((resolve) => uiControlServer.close(() => resolve(undefined)));\n    uiControlServer = null;","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/desktop/electron/ui-control-server.mjs#L149-L185","documentation":"Thrown by `start` in ui-control-server.mjs after the control HTTP server binds to an ephemeral port on 127.0.0.1, if `server.address()` does not yield a usable port. This is a defensive check: a null port means the listening socket did not report an address, so the UI control bridge cannot be advertised in the discovery file and startup aborts.","triggerScenarios":"`uiControlServer.address()` returns null or a non-object (e.g. the server closed between the listen callback and the address read, or an unusual handle/state), making `port` null and tripping the guard.","commonSituations":"Server closed externally right after startup; IPv6/pipe-shaped address handling assumptions broken; a race where another component tears down the server during init; exotic environments where address() behaves unexpectedly.","solutions":["Investigate why the server closed or address() returned null right after a successful listen","Add an error/close listener on the server before listen() to capture the real cause","Retry the start sequence; if persistent, log the address() result for diagnosis"],"exampleFix":"// before\nuiControlServer.listen(0, '127.0.0.1', () => resolve(undefined));\n// after\nuiControlServer.on('close', () => console.error('control server closed early'));\nuiControlServer.listen(0, '127.0.0.1', () => resolve(undefined));","handlingStrategy":"retry","validationCode":"function addressHasPort(address) {\n  return typeof address === 'object' && address !== null && typeof address.port === 'number' && address.port > 0;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await startUiControlBridge();\n} catch (e) {\n  if (e.message === 'Could not start OpenWork UI control bridge.') {\n    await retryWithBackoff(startUiControlBridge, 3);\n  } else throw e;\n}","preventionTips":["Attach error/close listeners to the server before listen()","Keep a reference to the server and don't close it during startup","Log server.address() on failure for diagnosis","Retry the ephemeral-port bind once on failure"],"tags":["electron","server","startup","ipc"],"backgroundTag":"server-bind-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}