{"record":{"id":"62b833a52897a684","repo":"moeru-ai/airi","slug":"hearing-module-failed-to-stop-playground-monitor","errorCode":null,"errorMessage":"[Hearing Module] Failed to stop playground monitoring:","messagePattern":"\\[Hearing Module\\] Failed to stop playground monitoring:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-pages/src/pages/settings/modules/hearing.vue","lineNumber":331,"sourceCode":"\n  await hearingStore.loadModelsForProvider(provider)\n  syncOpenAICompatibleSettings()\n\n  const models = providerModels.value\n  if (models.length > 0 && !models.some(model => model.id === activeTranscriptionModel.value))\n    activeTranscriptionModel.value = models[0].id\n\n  if (shouldRestartMonitoring)\n    isMonitoring.value = await setupAudioMonitoring()\n}, { immediate: true })\n\nonMounted(async () => {\n  syncOpenAICompatibleSettings()\n  await askPermission()\n})\n\nonUnmounted(() => {\n  void stopAudioMonitoring().catch(cause => console.warn('[Hearing Module] Failed to stop playground monitoring:', cause))\n})\n</script>\n\n<template>\n  <div flex=\"~ col md:row gap-6\">\n    <div bg=\"neutral-100 dark:[rgba(0,0,0,0.3)]\" rounded-xl p-4 flex=\"~ col gap-4\" class=\"h-fit w-full md:w-[40%]\">\n      <div flex=\"~ col gap-4\">\n        <!-- Audio Input Selection -->\n        <div>\n          <FieldCombobox\n            v-model=\"selectedAudioInput\"\n            label=\"Audio Input Device\"\n            description=\"Select the audio input device for your hearing module.\"\n            :options=\"audioInputOptions\"\n            placeholder=\"Select an audio input device\"\n            layout=\"vertical\"\n          />\n        </div>","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-pages/src/pages/settings/modules/hearing.vue#L313-L349","documentation":"During component unmount, the hearing playground fires stopAudioMonitoring() (async teardown of the transcription session, VAD, and stream) as void with a .catch that logs this warning when teardown rejects. Common when stopping something that never fully started. It is deliberately fire-and-forget so unmount never throws; the warn records the cleanup failure cause.","triggerScenarios":"Unmounting while monitoring never fully started (earlier setup failure); stopping a VAD or provider session whose stop path throws; HMR double-unmount tearing down twice; stopping after the underlying MediaStream was already released elsewhere.","commonSituations":"Navigating away from hearing settings immediately after toggling monitoring on; dev HMR remount cycles; secondary errors cascading from an earlier permission/stream failure.","solutions":["Check the logged cause - it names which stop step rejected","Fix the primary setup failure if this follows an earlier error - cleanup warnings are usually secondary","Make the stop path idempotent so stopping a non-started session resolves instead of rejecting","Safe to disregard in dev HMR unmounts when monitoring state is otherwise consistent"],"exampleFix":"// before\nonUnmounted(() => {\n  void stopAudioMonitoring().catch(cause => console.warn('[Hearing Module] Failed to stop playground monitoring:', cause))\n})\n\n// after - skip teardown when nothing is running\nonUnmounted(() => {\n  if (!isMonitoring.value)\n    return\n  void stopAudioMonitoring().catch(cause => console.warn('[Hearing Module] Failed to stop playground monitoring:', cause))\n})","handlingStrategy":"try-catch","validationCode":"if (!isMonitoring.value)\n  return\nawait stopAudioMonitoring()","typeGuard":null,"tryCatchPattern":"onUnmounted(() => {\n  if (!isMonitoring.value)\n    return\n  void stopAudioMonitoring().catch((cause) => {\n    if (import.meta.env.DEV)\n      console.warn('[Hearing Module] Failed to stop playground monitoring:', cause)\n  })\n})","preventionTips":["Make stop paths idempotent - stopping a non-started session should resolve, not reject","Skip teardown when monitoring never started (check isMonitoring first)","Never let async teardown throw during unmount; always attach a catch","Fix primary setup failures early - cleanup warnings are usually secondary"],"tags":["cleanup","unmount","lifecycle","hearing","async-teardown"],"backgroundTag":"cleanup-teardown-failed","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}