{"record":{"id":"7470568461c5204f","repo":"moeru-ai/airi","slug":"error-stopping-recognition-instance","errorCode":null,"errorMessage":"Error stopping recognition instance:","messagePattern":"Error stopping recognition instance:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-pages/src/pages/settings/providers/transcription/browser-web-speech-api.vue","lineNumber":261,"sourceCode":"    testStatusMessage.value = `Error: ${testTranscriptionError.value}`\n    isTranscribing.value = false\n    isTestingSTT.value = false\n    console.error('Web Speech API test error:', err)\n  }\n}\n\nasync function stopSTTTest() {\n  isTestingSTT.value = false\n  isTranscribing.value = false\n  testStatusMessage.value = 'Stopped'\n\n  try {\n    // Stop recognition instance if we have one\n    if (testRecognitionInstance.value) {\n      try {\n        testRecognitionInstance.value.stop()\n      }\n      catch (err) { console.warn('Error stopping recognition instance:', err) }\n      testRecognitionInstance.value = null\n    }\n\n    // Abort the abort controller\n    if (testAbortController.value && !testAbortController.value.signal.aborted) {\n      testAbortController.value.abort()\n      testAbortController.value = null\n    }\n  }\n  catch (err) {\n    console.error('Error stopping STT test:', err)\n  }\n\n  // Finalize transcription if we have streaming text\n  if (testStreamingText.value.trim() && !testTranscriptionText.value) {\n    testTranscriptionText.value = testStreamingText.value.trim()\n  }\n","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-pages/src/pages/settings/providers/transcription/browser-web-speech-api.vue#L243-L279","documentation":"In the transcription provider settings test, testRecognitionInstance.value.stop() threw during stopSTTTest — usually because the recognition already stopped or was aborted first. The nested catch keeps the outer teardown going: the instance reference is nulled and the abort controller fires afterwards. UI state still lands on 'Stopped'.","triggerScenarios":"Clicking Stop after the test recognition already ended; the test timeout aborted the controller first; double-clicking the stop button.","commonSituations":"Tester double-clicks Stop; test timed out and the user clicks Stop afterwards; permission prompt dismissed mid-test.","solutions":["Ignore the warning — UI state resets to 'Stopped' regardless","Make stopSTTTest idempotent: early-return when isTestingSTT is already false","Null the instance reference before calling stop() to prevent double-stop","Catch InvalidStateError specifically and stay quiet on it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!testRecognitionInstance.value) return // nothing to stop (source guard)","typeGuard":null,"tryCatchPattern":"try {\n  testRecognitionInstance.value.stop()\n}\ncatch (err) {\n  console.warn('Error stopping recognition instance:', err) // InvalidStateError expected on double-stop\n}\ntestRecognitionInstance.value = null // always drop the reference (source pattern)","preventionTips":["Make stopSTTTest idempotent: early-return when isTestingSTT is already false","Abort the controller before stopping recognition to avoid double-stop races","Ignore InvalidStateError from recognition.stop(); the instance is discarded anyway"],"tags":["settings","web-speech-api","stop","stt-test"],"backgroundTag":"web-speech-api-invalid-state","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}