{"record":{"id":"0177db577b59eba0","repo":"tinyhumansai/openhuman","slug":"ptt-audio-start-failed","errorCode":null,"errorMessage":"[ptt] audio start failed","messagePattern":"\\[ptt\\] audio start failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/pttService.ts","lineNumber":213,"sourceCode":"        startedAtMs: deps.now(),\n        watchdogTimer: null,\n        finalizedByWatchdog: false,\n      };\n      const claimed = active;\n\n      await deps.playChime('open');\n      await deps.showOverlay(true, sessionId);\n\n      // If a concurrent onStart preempted us during the awaits, our claim was\n      // replaced. Stop here — the new claim owns the slot.\n      if (active !== claimed) {\n        return;\n      }\n\n      try {\n        await deps.audioCapture.start({ sessionTag: `ptt:${sessionId}` });\n      } catch (err) {\n        deps.logger.warn('[ptt] audio start failed', { sessionId, err: String(err) });\n        if (active === claimed) {\n          active = null;\n        }\n        await deps.playChime('error');\n        await deps.showOverlay(false, sessionId);\n        return;\n      }\n\n      // Re-check after the audio.start await.\n      if (active !== claimed) {\n        // Concurrent preempt replaced our claim mid-flight; we already started\n        // audio for an orphan session. Best-effort cancel and exit — cancellation\n        // failure here is non-actionable (the orphan session is already detached).\n        try {\n          await deps.audioCapture.cancel();\n        } catch (_) {\n          // ignore: orphan-session cleanup is best-effort\n        }","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/pttService.ts#L195-L231","documentation":"Starting the microphone capture for a new push-to-talk session failed: deps.audioCapture.start({sessionTag}) threw after the session claimed the active slot, played the open chime, and showed the overlay. The session is left in a broken claimed state (audio never starts), so the user sees/heard a session begin that cannot record.","triggerScenarios":"Thrown at app/src/services/pttService.ts:213 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check the err string for the capture backend's reason — device busy, permission denied, or no device found","Verify OS microphone permission has been granted to the app (the inference-gate mic-permission probe reports Unknown when compiled out)","Confirm no other application holds exclusive access to the input device","Restart the app if the audio subsystem is in a bad state — the active session slot is not automatically released on this failure"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}