{"record":{"id":"bb0a18d0d1c48cf5","repo":"moeru-ai/airi","slug":"godot-stage-bridge-is-not-connected","errorCode":null,"errorMessage":"Godot stage bridge is not connected.","messagePattern":"Godot stage bridge is not connected\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/godot-stage/index.ts","lineNumber":481,"sourceCode":"  }\n\n  function sendSocketMessage(type: string, payload?: unknown) {\n    if (!currentSocketPeer) {\n      return false\n    }\n\n    currentSocketPeer.send(createSocketEnvelope(type, payload))\n    return true\n  }\n\n  function sendViewRequest(type: 'host.view.patch' | 'host.view.request_snapshot', payload: Record<string, unknown> = {}) {\n    if (currentStatus.state !== 'running') {\n      throw new Error('Godot stage is not running.')\n    }\n\n    const requestId = randomUUID()\n    if (!sendSocketMessage(type, { requestId, ...payload })) {\n      throw new Error('Godot stage bridge is not connected.')\n    }\n\n    return { requestId }\n  }\n\n  function sendSceneInputToGodot(payload: GodotStageSceneApplyPayload) {\n    if (!sendSocketMessage('host.scene.apply', payload)) {\n      throw new Error('Godot stage bridge is not connected.')\n    }\n  }\n\n  function handleSocketMessage(message: GodotStageSocketEnvelope) {\n    switch (message.type) {\n      case 'stage.ready': {\n        setStatus({\n          state: 'running',\n          pid: currentProcess?.pid ?? null,\n          lastError: undefined,","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/apps/stage-tamagotchi/src/main/services/airi/godot-stage/index.ts#L463-L499","documentation":"Thrown by sendViewRequest after currentStatus.state === 'running' passed but sendSocketMessage returned false — meaning currentSocketPeer is null/absent. So the stage is marked running but the websocket bridge peer (the Godot process connection) is not established, making it impossible to deliver the host.view.* message.","triggerScenarios":"The Godot process is alive enough to have set state 'running' but the inbound websocket peer disconnected or was never assigned to currentSocketPeer; transient window between the process starting and the socket peer opening; peer dropped mid-session.","commonSituations":"Godot process crashed but the 'stopped' status didn't propagate yet; websocket connection from Godot dropped due to restart of the socket runtime; race between setStatus('running') and peer assignment.","solutions":["Treat as transient: retry after a short delay, or restart the Godot stage with electronGodotStageStart to re-establish the peer.","Check electronGodotStageGetStatus and the lastError field for an underlying socket/process failure.","Ensure the socket runtime (startSocketRuntime) stayed up alongside the Godot process."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await electronGodotStageApplyViewPatch({ patches })\n}\ncatch (error) {\n  if (errorMessageFrom(error) === 'Godot stage bridge is not connected.') {\n    // transient: restart the stage, then retry once\n    await electronGodotStageStart()\n    await electronGodotStageApplyViewPatch({ patches })\n  }\n}","preventionTips":["Treat 'not connected' as transient; restart the stage and retry.","Verify the socket runtime stays up alongside the Godot process.","Watch lastError in the status object for socket failures."],"tags":["godot-stage","websocket","ipc","electron","lifecycle","connection"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}