moeru-ai/airi · error · Error

WebSocket transport is not implemented for node runtime yet.

Error message

WebSocket transport is not implemented for node runtime yet.

What it means

Thrown by createPluginContext in the node runtime when transport.kind === 'websocket'. The node runtime's transport switch currently implements only 'in-memory'; a WebSocket-based Eventa context is planned but not implemented, so requesting it is an explicit hard stop rather than silent degradation.

Solutions

  1. Use the implemented transport for node: createPluginContext({ kind: 'in-memory' }).
  2. Keep the remote-transport plan but gate it: select 'websocket' only when the runtime that supports it is available, falling back to 'in-memory' in Node.
  3. Upgrade plugin-sdk and re-check runtimes/node/index.ts — the switch is the source of truth for what is implemented.
  4. For true process isolation today, run a separate host process and bridge at the application layer instead of the plugin transport.

Example fix

// before
const ctx = createPluginContext({ kind: 'websocket', url: 'ws://localhost:8081' }) // node runtime: throws

// after
const ctx = createPluginContext({ kind: 'in-memory' })
Defensive patterns

Strategy: type-guard

Validate before calling

// Node runtime: only 'in-memory' is implemented.
if (transport.kind !== 'in-memory') {
  throw new Error(`Node plugin host supports only 'in-memory' transport, got '${transport.kind}'`)
}

Type guard

type NodeSupportedTransport = Extract<PluginTransport, { kind: 'in-memory' }>
const isNodeSupportedTransport = (t: PluginTransport): t is NodeSupportedTransport => t.kind === 'in-memory'

Try / catch

try {
  ctx = createPluginContext(transport)
} catch (error) {
  if (error instanceof Error && error.message.includes('not implemented for node runtime')) {
    ctx = createPluginContext({ kind: 'in-memory' }) // deliberate fallback only if acceptable
  } else {
    throw error
  }
}

Prevention

When it happens

Trigger: Bootstrapping a node extension session with createPluginContext({ kind: 'websocket', url: 'ws://...' }); a shared config object that picks websocket for all environments being reused in a Node host; migrating an extension host from in-memory to remote WebSocket transport before the node implementation landed.

Common situations: Trying to host extensions out-of-process over a WebSocket from a Node server; copying transport config from a browser prototype into Node tooling; version skew where docs mention websocket support that the installed plugin-sdk version does not ship.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/0f805c586d7edb3f. Report an issue: GitHub.

Appendix: source

Thrown at packages/plugin-sdk/src/plugin-host/runtimes/node/index.ts:29

/**
 * Creates the Eventa context used by node-side extension host sessions.
 *
 * Use when:
 * - Bootstrapping a node runtime extension session
 *
 * Expects:
 * - `transport` describes a transport supported by the node runtime
 *
 * Returns:
 * - A node-compatible Eventa context, or throws if the transport is not implemented
 */
export function createPluginContext(transport: PluginTransport): EventContext<any, any> {
  switch (transport.kind) {
    case 'in-memory':
      return createContext()
    case 'websocket':
      throw new Error('WebSocket transport is not implemented for node runtime yet.')
    case 'node-worker':
      throw new Error('Node worker transport is not implemented yet.')
    case 'electron':
      throw new Error('Electron transport is not implemented yet.')
    case 'web-worker':
      throw new Error('Web worker transport is not available in node runtime.')
    default:
      throw new Error('Unknown plugin transport kind.')
  }
}

View on GitHub (pinned to 677329427f)