moeru-ai/airi · warning

[Kokoro Worker] Unknown message type:

Error message

[Kokoro Worker] Unknown message type:

What it means

The Kokoro TTS worker's inbound message switch handles exactly 'load-model', 'run-inference', 'unload-model', and 'cancel'. Any other message.type falls into default, logs this warning with the received type, and is then dropped - no reply and no error is sent, so a caller awaiting that requestId would hang until its timeout.

Source

Thrown at packages/stage-ui/src/workers/kokoro/worker.ts:302

  switch (message.type) {
    case 'load-model':
      await loadModel(message)
      break
    case 'run-inference':
      await runInference(message as RunInferenceRequest<KokoroInferenceInput>)
      break
    case 'unload-model':
      ttsModel = null
      currentQuantization = null
      currentDevice = null
      globalThis.postMessage({ type: 'model-unloaded', requestId: message.requestId })
      break
    case 'cancel':
      markCancelled(message.targetRequestId)
      break
    default:
      console.warn('[Kokoro Worker] Unknown message type:', (message as any).type)
  }
})

View on GitHub (pinned to 677329427f)

Solutions

  1. Compare the logged type against the WorkerInboundMessage union in the worker protocol module
  2. Hard-reload or restart the app so main thread and worker come from the same bundle
  3. Add the missing case in the worker switch (or reply with an error) if you extended the protocol
  4. Use the typed request helpers instead of hand-built postMessage payloads

Example fix

// before
switch (message.type) {
  case 'load-model': ...
  default: console.warn('[Kokoro Worker] Unknown message type:', (message as any).type)
}

// after - compile-time exhaustiveness plus an error reply so callers do not hang
default: {
  const _exhaustive: never = message
  sendError(message.requestId, new Error(`Unknown message type: ${(message as any).type}`), 'protocol')
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!isKnownKokoroMessage(message)) {
  console.warn('dropping unknown worker message:', message)
  return
}

Type guard

type KnownKokoroMessage =
  | { type: 'load-model' }
  | { type: 'run-inference' }
  | { type: 'unload-model' }
  | { type: 'cancel' }
function isKnownKokoroMessage(m: unknown): m is KnownKokoroMessage {
  return typeof m === 'object' && m !== null
    && ['load-model', 'run-inference', 'unload-model', 'cancel'].includes((m as { type: unknown }).type as string)
}

Try / catch

default: {
  const _exhaustive: never = message
  sendError(message.requestId, new Error(`Unknown message type: ${(message as any).type}`), 'protocol')
}

Prevention

When it happens

Trigger: Main thread and worker built from different versions after a deploy (new message type exists on one side only); raw postMessage with a typo'd or renamed type; dev HMR leaving a stale worker alive that receives new-protocol messages; external code posting into the worker.

Common situations: Version skew between bundles after upgrades without a hard reload; developing a new worker message and forgetting the worker-side case; recorded/replayed messages with outdated shapes.

Related errors


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