{"record":{"id":"79e19a2f46b63ead","repo":"moeru-ai/airi","slug":"failed-to-handle-spark-notify-event","errorCode":null,"errorMessage":"Failed to handle spark:notify event:","messagePattern":"Failed to handle spark:notify event:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-ui/src/stores/character/orchestrator/store.ts","lineNumber":277,"sourceCode":"\n  async function handleSparkEmit(_: WebSocketBaseEvent<'spark:emit', WebSocketEvents['spark:emit']>) {\n    // Currently no-op\n    return undefined\n  }\n\n  function initialize() {\n    if (initialized)\n      return\n\n    initialized = true\n\n    eventUnsubscribes.push(\n      modsServerChannelStore.onEvent('spark:notify', async (event) => {\n        try {\n          await handleIncomingSparkNotify(event)\n        }\n        catch (error) {\n          console.warn('Failed to handle spark:notify event:', error)\n        }\n      }),\n    )\n\n    eventUnsubscribes.push(\n      modsServerChannelStore.onEvent('spark:emit', async (event) => {\n        try {\n          await handleSparkEmit(event)\n        }\n        catch (error) {\n          console.warn('Failed to handle spark:emit event:', error)\n        }\n      }),\n    )\n\n    startTicker()\n  }\n","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/stores/character/orchestrator/store.ts#L259-L295","documentation":"The orchestrator's initialize() subscribes to 'spark:notify' events from the mods server channel; when the async handler handleIncomingSparkNotify rejects, the error is caught per-event and logged. The event is not retried at this layer (retry scheduling lives inside the queue processing), and the subscription stays alive, so one bad event does not kill the listener.","triggerScenarios":"A spark:notify event arrives whose processing throws — invalid event payload, scheduling logic rejecting the event, or the same processSparkNotify path failing before/while entering the retry queue.","commonSituations":"Mod emitting an event with unexpected/missing fields; version skew between mod SDK and orchestrator schema; a bug in computeNextRunAt/scheduling for edge-case payloads; downstream store state not initialized when the event lands.","solutions":["Inspect the logged error to find the throwing frame inside handleIncomingSparkNotify.","Validate/normalize incoming spark event payloads at the channel boundary before dispatch.","Update mods and orchestrator to the same event schema version.","If it fires once at startup before stores are ready, defer initialize() until dependent stores are initialized."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"function isSparkNotifyPayload(event: unknown): event is { /* expected shape */ } {\n  // validate with a schema (Valibot) at the channel boundary\n  return sparkNotifySchema.safeParse(event).success\n}","typeGuard":null,"tryCatchPattern":"modsServerChannelStore.onEvent('spark:notify', async (event) => {\n  try {\n    await handleIncomingSparkNotify(event)\n  }\n  catch (error) {\n    console.warn('Failed to handle spark:notify event:', error)\n    // subscription stays alive; isolate the failure to this event\n  }\n})","preventionTips":["Schema-validate incoming events before dispatch so bad payloads are rejected loudly with context.","Keep handler side-effects idempotent so a retried event cannot double-apply.","Initialize dependent stores before subscribing in initialize()."],"tags":["orchestrator","spark","event-handler","mods"],"backgroundTag":"event-handler-exception","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}