moeru-ai/airi · error · Error

Godot stage is not running.

Error message

Godot stage is not running.

What it means

Thrown by sendViewRequest (used by applyViewPatch / requestViewSnapshot) when currentStatus.state !== 'running'. The Godot stage must be in the running state for view mutations to be sent; any earlier state (idle/starting/stopped/errored) causes this guard to throw before issuing a request id.

Source

Thrown at apps/stage-tamagotchi/src/main/services/airi/godot-stage/index.ts:476

    // Startup failed after spawning Godot; release the child process before
    // allowing the renderer to retry and create another stage runtime.
    activeProcess.kill()

    await waitForProcessExit(exitPromise, 2_000)
  }

  function sendSocketMessage(type: string, payload?: unknown) {
    if (!currentSocketPeer) {
      return false
    }

    currentSocketPeer.send(createSocketEnvelope(type, payload))
    return true
  }

  function sendViewRequest(type: 'host.view.patch' | 'host.view.request_snapshot', payload: Record<string, unknown> = {}) {
    if (currentStatus.state !== 'running') {
      throw new Error('Godot stage is not running.')
    }

    const requestId = randomUUID()
    if (!sendSocketMessage(type, { requestId, ...payload })) {
      throw new Error('Godot stage bridge is not connected.')
    }

    return { requestId }
  }

  function sendSceneInputToGodot(payload: GodotStageSceneApplyPayload) {
    if (!sendSocketMessage('host.scene.apply', payload)) {
      throw new Error('Godot stage bridge is not connected.')
    }
  }

  function handleSocketMessage(message: GodotStageSocketEnvelope) {
    switch (message.type) {

View on GitHub (pinned to 27111382b4)

Solutions

  1. Await electronGodotStageStart and wait until electronGodotStageGetStatus returns state 'running' before issuing view requests.
  2. Subscribe to electronGodotStageStatusChanged and gate view calls on the running state.
  3. After a stop or error, restart the stage before retrying view operations.
  4. Handle the thrown error in the renderer and surface a 'stage not ready' UI instead of retrying blindly.

Example fix

// before
await electronGodotStageApplyViewPatch({ patches })

// after
const status = await electronGodotStageGetStatus()
if (status.state !== 'running') {
  await electronGodotStageStart()
}
await electronGodotStageApplyViewPatch({ patches })
Defensive patterns

Strategy: validation

Validate before calling

async function stageIsRunning(): Promise<boolean> {
  return (await electronGodotStageGetStatus()).state === 'running'
}

Type guard

async function stageIsRunning(): Promise<boolean> {
  return (await electronGodotStageGetStatus()).state === 'running'
}

Prevention

When it happens

Trigger: Calling electronGodotStageApplyViewPatch or electronGodotStageRequestViewSnapshot before the stage has reported 'stage.ready', after it was stopped, or after it crashed.

Common situations: Renderer issues a view patch immediately at startup before the Godot process finishes booting; calling after stop(); calling after a stage crash where state flipped to 'errored'/'stopped'; race where the ready deferred hasn't resolved.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/aafcdc1b206f434f. Report an issue: GitHub.